LCOV - code coverage report
Current view: top level - source3/smbd - nttrans.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 1041 1537 67.7 %
Date: 2021-09-23 10:06:22 Functions: 33 45 73.3 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB NT transaction handling
       4             :    Copyright (C) Jeremy Allison                 1994-2007
       5             :    Copyright (C) Stefan (metze) Metzmacher      2003
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "system/filesys.h"
      23             : #include "smbd/smbd.h"
      24             : #include "smbd/globals.h"
      25             : #include "fake_file.h"
      26             : #include "../libcli/security/security.h"
      27             : #include "../librpc/gen_ndr/ndr_security.h"
      28             : #include "passdb/lookup_sid.h"
      29             : #include "auth.h"
      30             : #include "smbprofile.h"
      31             : #include "libsmb/libsmb.h"
      32             : #include "lib/util_ea.h"
      33             : #include "librpc/gen_ndr/ndr_quota.h"
      34             : #include "librpc/gen_ndr/ndr_security.h"
      35             : 
      36             : extern const struct generic_mapping file_generic_mapping;
      37             : 
      38       15059 : static char *nttrans_realloc(char **ptr, size_t size)
      39             : {
      40       15059 :         if (ptr==NULL) {
      41           0 :                 smb_panic("nttrans_realloc() called with NULL ptr");
      42             :         }
      43             : 
      44       15059 :         *ptr = (char *)SMB_REALLOC(*ptr, size);
      45       15059 :         if(*ptr == NULL) {
      46           0 :                 return NULL;
      47             :         }
      48       15100 :         memset(*ptr,'\0',size);
      49       15059 :         return *ptr;
      50             : }
      51             : 
      52             : /****************************************************************************
      53             :  Send the required number of replies back.
      54             :  We assume all fields other than the data fields are
      55             :  set correctly for the type of call.
      56             :  HACK ! Always assumes smb_setup field is zero.
      57             : ****************************************************************************/
      58             : 
      59       16648 : static void send_nt_replies(connection_struct *conn,
      60             :                             struct smb_request *req, NTSTATUS nt_error,
      61             :                             char *params, int paramsize,
      62             :                             char *pdata, int datasize)
      63             : {
      64       16648 :         int data_to_send = datasize;
      65       16648 :         int params_to_send = paramsize;
      66             :         int useable_space;
      67       16648 :         char *pp = params;
      68       16648 :         char *pd = pdata;
      69             :         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
      70       16648 :         int alignment_offset = 1;
      71       16648 :         int data_alignment_offset = 0;
      72       16648 :         struct smbXsrv_connection *xconn = req->xconn;
      73       16648 :         int max_send = xconn->smb1.sessions.max_send;
      74             : 
      75             :         /*
      76             :          * If there genuinely are no parameters or data to send just send
      77             :          * the empty packet.
      78             :          */
      79             : 
      80       16648 :         if(params_to_send == 0 && data_to_send == 0) {
      81        7539 :                 reply_outbuf(req, 18, 0);
      82        7539 :                 if (NT_STATUS_V(nt_error)) {
      83         922 :                         error_packet_set((char *)req->outbuf,
      84             :                                          0, 0, nt_error,
      85             :                                          __LINE__,__FILE__);
      86             :                 }
      87        7539 :                 show_msg((char *)req->outbuf);
      88       28548 :                 if (!srv_send_smb(xconn,
      89        7539 :                                 (char *)req->outbuf,
      90        7539 :                                 true, req->seqnum+1,
      91        7539 :                                 IS_CONN_ENCRYPTED(conn),
      92             :                                 &req->pcd)) {
      93           0 :                         exit_server_cleanly("send_nt_replies: srv_send_smb failed.");
      94             :                 }
      95        7539 :                 TALLOC_FREE(req->outbuf);
      96        7534 :                 return;
      97             :         }
      98             : 
      99             :         /*
     100             :          * When sending params and data ensure that both are nicely aligned.
     101             :          * Only do this alignment when there is also data to send - else
     102             :          * can cause NT redirector problems.
     103             :          */
     104             : 
     105        9109 :         if (((params_to_send % 4) != 0) && (data_to_send != 0)) {
     106           0 :                 data_alignment_offset = 4 - (params_to_send % 4);
     107             :         }
     108             : 
     109             :         /*
     110             :          * Space is bufsize minus Netbios over TCP header minus SMB header.
     111             :          * The alignment_offset is to align the param bytes on a four byte
     112             :          * boundary (2 bytes for data len, one byte pad).
     113             :          * NT needs this to work correctly.
     114             :          */
     115             : 
     116        9109 :         useable_space = max_send - (smb_size
     117             :                                     + 2 * 18 /* wct */
     118        9068 :                                     + alignment_offset
     119        9109 :                                     + data_alignment_offset);
     120             : 
     121        9109 :         if (useable_space < 0) {
     122           0 :                 char *msg = talloc_asprintf(
     123           0 :                         talloc_tos(),
     124             :                         "send_nt_replies failed sanity useable_space = %d!!!",
     125             :                         useable_space);
     126           0 :                 DEBUG(0, ("%s\n", msg));
     127           0 :                 exit_server_cleanly(msg);
     128             :         }
     129             : 
     130       26654 :         while (params_to_send || data_to_send) {
     131             : 
     132             :                 /*
     133             :                  * Calculate whether we will totally or partially fill this packet.
     134             :                  */
     135             : 
     136        9109 :                 total_sent_thistime = params_to_send + data_to_send;
     137             : 
     138             :                 /*
     139             :                  * We can never send more than useable_space.
     140             :                  */
     141             : 
     142        9109 :                 total_sent_thistime = MIN(total_sent_thistime, useable_space);
     143             : 
     144        9109 :                 reply_outbuf(req, 18,
     145        9109 :                              total_sent_thistime + alignment_offset
     146        9109 :                              + data_alignment_offset);
     147             : 
     148             :                 /*
     149             :                  * Set total params and data to be sent.
     150             :                  */
     151             : 
     152        9109 :                 SIVAL(req->outbuf,smb_ntr_TotalParameterCount,paramsize);
     153        9109 :                 SIVAL(req->outbuf,smb_ntr_TotalDataCount,datasize);
     154             : 
     155             :                 /*
     156             :                  * Calculate how many parameters and data we can fit into
     157             :                  * this packet. Parameters get precedence.
     158             :                  */
     159             : 
     160        9109 :                 params_sent_thistime = MIN(params_to_send,useable_space);
     161        9109 :                 data_sent_thistime = useable_space - params_sent_thistime;
     162        9109 :                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
     163             : 
     164        9109 :                 SIVAL(req->outbuf, smb_ntr_ParameterCount,
     165             :                       params_sent_thistime);
     166             : 
     167        9109 :                 if(params_sent_thistime == 0) {
     168        1244 :                         SIVAL(req->outbuf,smb_ntr_ParameterOffset,0);
     169        1244 :                         SIVAL(req->outbuf,smb_ntr_ParameterDisplacement,0);
     170             :                 } else {
     171             :                         /*
     172             :                          * smb_ntr_ParameterOffset is the offset from the start of the SMB header to the
     173             :                          * parameter bytes, however the first 4 bytes of outbuf are
     174             :                          * the Netbios over TCP header. Thus use smb_base() to subtract
     175             :                          * them from the calculation.
     176             :                          */
     177             : 
     178        7865 :                         SIVAL(req->outbuf,smb_ntr_ParameterOffset,
     179             :                               ((smb_buf(req->outbuf)+alignment_offset)
     180             :                                - smb_base(req->outbuf)));
     181             :                         /*
     182             :                          * Absolute displacement of param bytes sent in this packet.
     183             :                          */
     184             : 
     185        7865 :                         SIVAL(req->outbuf, smb_ntr_ParameterDisplacement,
     186             :                               pp - params);
     187             :                 }
     188             : 
     189             :                 /*
     190             :                  * Deal with the data portion.
     191             :                  */
     192             : 
     193        9109 :                 SIVAL(req->outbuf, smb_ntr_DataCount, data_sent_thistime);
     194             : 
     195        9109 :                 if(data_sent_thistime == 0) {
     196         557 :                         SIVAL(req->outbuf,smb_ntr_DataOffset,0);
     197         557 :                         SIVAL(req->outbuf,smb_ntr_DataDisplacement, 0);
     198             :                 } else {
     199             :                         /*
     200             :                          * The offset of the data bytes is the offset of the
     201             :                          * parameter bytes plus the number of parameters being sent this time.
     202             :                          */
     203             : 
     204        8552 :                         SIVAL(req->outbuf, smb_ntr_DataOffset,
     205             :                               ((smb_buf(req->outbuf)+alignment_offset) -
     206             :                                smb_base(req->outbuf))
     207             :                               + params_sent_thistime + data_alignment_offset);
     208        8552 :                         SIVAL(req->outbuf,smb_ntr_DataDisplacement, pd - pdata);
     209             :                 }
     210             : 
     211             :                 /*
     212             :                  * Copy the param bytes into the packet.
     213             :                  */
     214             : 
     215        9109 :                 if(params_sent_thistime) {
     216        7824 :                         if (alignment_offset != 0) {
     217        7865 :                                 memset(smb_buf(req->outbuf), 0,
     218             :                                        alignment_offset);
     219             :                         }
     220        7865 :                         memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
     221             :                                params_sent_thistime);
     222             :                 }
     223             : 
     224             :                 /*
     225             :                  * Copy in the data bytes
     226             :                  */
     227             : 
     228        9109 :                 if(data_sent_thistime) {
     229        8552 :                         if (data_alignment_offset != 0) {
     230           0 :                                 memset((smb_buf(req->outbuf)+alignment_offset+
     231             :                                         params_sent_thistime), 0,
     232             :                                        data_alignment_offset);
     233             :                         }
     234       16533 :                         memcpy(smb_buf(req->outbuf)+alignment_offset
     235        8552 :                                +params_sent_thistime+data_alignment_offset,
     236             :                                pd,data_sent_thistime);
     237             :                 }
     238             : 
     239        9109 :                 DEBUG(9,("nt_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
     240             :                         params_sent_thistime, data_sent_thistime, useable_space));
     241        9109 :                 DEBUG(9,("nt_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
     242             :                         params_to_send, data_to_send, paramsize, datasize));
     243             : 
     244        9109 :                 if (NT_STATUS_V(nt_error)) {
     245           5 :                         error_packet_set((char *)req->outbuf,
     246             :                                          0, 0, nt_error,
     247             :                                          __LINE__,__FILE__);
     248             :                 }
     249             : 
     250             :                 /* Send the packet */
     251        9109 :                 show_msg((char *)req->outbuf);
     252       34540 :                 if (!srv_send_smb(xconn,
     253        9109 :                                 (char *)req->outbuf,
     254        9109 :                                 true, req->seqnum+1,
     255        9109 :                                 IS_CONN_ENCRYPTED(conn),
     256             :                                 &req->pcd)) {
     257           0 :                         exit_server_cleanly("send_nt_replies: srv_send_smb failed.");
     258             :                 }
     259             : 
     260        9109 :                 TALLOC_FREE(req->outbuf);
     261             : 
     262        9109 :                 pp += params_sent_thistime;
     263        9109 :                 pd += data_sent_thistime;
     264             : 
     265        9109 :                 params_to_send -= params_sent_thistime;
     266        9109 :                 data_to_send -= data_sent_thistime;
     267             : 
     268             :                 /*
     269             :                  * Sanity check
     270             :                  */
     271             : 
     272        9109 :                 if(params_to_send < 0 || data_to_send < 0) {
     273           0 :                         DEBUG(0,("send_nt_replies failed sanity check pts = %d, dts = %d\n!!!",
     274             :                                 params_to_send, data_to_send));
     275           0 :                         exit_server_cleanly("send_nt_replies: internal error");
     276             :                 }
     277             :         }
     278             : }
     279             : 
     280             : /****************************************************************************
     281             :  Reply to an NT create and X call on a pipe
     282             : ****************************************************************************/
     283             : 
     284         392 : static void nt_open_pipe(char *fname, connection_struct *conn,
     285             :                          struct smb_request *req, uint16_t *ppnum)
     286             : {
     287             :         files_struct *fsp;
     288             :         NTSTATUS status;
     289             : 
     290         392 :         DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname));
     291             : 
     292             :         /* Strip \\ off the name if present. */
     293        1101 :         while (fname[0] == '\\') {
     294         372 :                 fname++;
     295             :         }
     296             : 
     297         392 :         status = open_np_file(req, fname, &fsp);
     298         392 :         if (!NT_STATUS_IS_OK(status)) {
     299          24 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
     300          24 :                         reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
     301             :                                         ERRDOS, ERRbadpipe);
     302          24 :                         return;
     303             :                 }
     304           0 :                 reply_nterror(req, status);
     305           0 :                 return;
     306             :         }
     307             : 
     308         368 :         *ppnum = fsp->fnum;
     309         368 :         return;
     310             : }
     311             : 
     312             : /****************************************************************************
     313             :  Reply to an NT create and X call for pipes.
     314             : ****************************************************************************/
     315             : 
     316         368 : static void do_ntcreate_pipe_open(connection_struct *conn,
     317             :                                   struct smb_request *req)
     318             : {
     319         368 :         char *fname = NULL;
     320         368 :         uint16_t pnum = FNUM_FIELD_INVALID;
     321         368 :         char *p = NULL;
     322         368 :         uint32_t flags = IVAL(req->vwv+3, 1);
     323         368 :         TALLOC_CTX *ctx = talloc_tos();
     324             : 
     325         368 :         srvstr_pull_req_talloc(ctx, req, &fname, req->buf, STR_TERMINATE);
     326             : 
     327         368 :         if (!fname) {
     328           0 :                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
     329             :                                 ERRDOS, ERRbadpipe);
     330           0 :                 return;
     331             :         }
     332         368 :         nt_open_pipe(fname, conn, req, &pnum);
     333             : 
     334         368 :         if (req->outbuf) {
     335             :                 /* error reply */
     336          12 :                 return;
     337             :         }
     338             : 
     339             :         /*
     340             :          * Deal with pipe return.
     341             :          */
     342             : 
     343         356 :         if (flags & EXTENDED_RESPONSE_REQUIRED) {
     344             :                 /* This is very strange. We
     345             :                  * return 50 words, but only set
     346             :                  * the wcnt to 42 ? It's definitely
     347             :                  * what happens on the wire....
     348             :                  */
     349           0 :                 reply_outbuf(req, 50, 0);
     350           0 :                 SCVAL(req->outbuf,smb_wct,42);
     351             :         } else {
     352         356 :                 reply_outbuf(req, 34, 0);
     353             :         }
     354             : 
     355         356 :         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
     356         356 :         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
     357             : 
     358         356 :         p = (char *)req->outbuf + smb_vwv2;
     359         356 :         p++;
     360         356 :         SSVAL(p,0,pnum);
     361         356 :         p += 2;
     362         356 :         SIVAL(p,0,FILE_WAS_OPENED);
     363         356 :         p += 4;
     364         356 :         p += 32;
     365         356 :         SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */
     366         356 :         p += 20;
     367             :         /* File type. */
     368         356 :         SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE);
     369             :         /* Device state. */
     370         356 :         SSVAL(p,2, 0x5FF); /* ? */
     371         356 :         p += 4;
     372             : 
     373         356 :         if (flags & EXTENDED_RESPONSE_REQUIRED) {
     374           0 :                 p += 25;
     375           0 :                 SIVAL(p,0,FILE_GENERIC_ALL);
     376             :                 /*
     377             :                  * For pipes W2K3 seems to return
     378             :                  * 0x12019B next.
     379             :                  * This is ((FILE_GENERIC_READ|FILE_GENERIC_WRITE) & ~FILE_APPEND_DATA)
     380             :                  */
     381           0 :                 SIVAL(p,4,(FILE_GENERIC_READ|FILE_GENERIC_WRITE)&~FILE_APPEND_DATA);
     382             :         }
     383             : 
     384         356 :         DEBUG(5,("do_ntcreate_pipe_open: open pipe = %s\n", fname));
     385             : }
     386             : 
     387             : struct case_semantics_state {
     388             :         connection_struct *conn;
     389             :         bool case_sensitive;
     390             :         bool case_preserve;
     391             :         bool short_case_preserve;
     392             : };
     393             : 
     394             : /****************************************************************************
     395             :  Restore case semantics.
     396             : ****************************************************************************/
     397             : 
     398           4 : static int restore_case_semantics(struct case_semantics_state *state)
     399             : {
     400           4 :         state->conn->case_sensitive = state->case_sensitive;
     401           4 :         state->conn->case_preserve = state->case_preserve;
     402           4 :         state->conn->short_case_preserve = state->short_case_preserve;
     403           4 :         return 0;
     404             : }
     405             : 
     406             : /****************************************************************************
     407             :  Save case semantics.
     408             : ****************************************************************************/
     409             : 
     410           4 : static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx,
     411             :                                                 connection_struct *conn)
     412             : {
     413             :         struct case_semantics_state *result;
     414             : 
     415           4 :         if (!(result = talloc(mem_ctx, struct case_semantics_state))) {
     416           0 :                 return NULL;
     417             :         }
     418             : 
     419           4 :         result->conn = conn;
     420           4 :         result->case_sensitive = conn->case_sensitive;
     421           4 :         result->case_preserve = conn->case_preserve;
     422           4 :         result->short_case_preserve = conn->short_case_preserve;
     423             : 
     424             :         /* Set to POSIX. */
     425           4 :         conn->case_sensitive = True;
     426           4 :         conn->case_preserve = True;
     427           4 :         conn->short_case_preserve = True;
     428             : 
     429           4 :         talloc_set_destructor(result, restore_case_semantics);
     430             : 
     431           4 :         return result;
     432             : }
     433             : 
     434             : /*
     435             :  * Calculate the full path name given a relative fid.
     436             :  */
     437         552 : static NTSTATUS get_relative_fid_filename(connection_struct *conn,
     438             :                                           struct smb_request *req,
     439             :                                           uint16_t root_dir_fid,
     440             :                                           char *path,
     441             :                                           char **path_out)
     442             : {
     443         552 :         struct files_struct *dir_fsp = NULL;
     444         552 :         char *new_path = NULL;
     445             : 
     446         552 :         if (root_dir_fid == 0 || path == NULL) {
     447           0 :                 return NT_STATUS_INTERNAL_ERROR;
     448             :         }
     449             : 
     450         552 :         dir_fsp = file_fsp(req, root_dir_fid);
     451         552 :         if (dir_fsp == NULL) {
     452           0 :                 return NT_STATUS_INVALID_HANDLE;
     453             :         }
     454             : 
     455         552 :         if (is_ntfs_stream_smb_fname(dir_fsp->fsp_name)) {
     456           0 :                 return NT_STATUS_INVALID_HANDLE;
     457             :         }
     458             : 
     459         552 :         if (!dir_fsp->fsp_flags.is_directory) {
     460             :                 /*
     461             :                  * Check to see if this is a mac fork of some kind.
     462             :                  */
     463           0 :                 if (conn->fs_capabilities & FILE_NAMED_STREAMS) {
     464           0 :                         char *stream = NULL;
     465             : 
     466           0 :                         stream = strchr_m(path, ':');
     467           0 :                         if (stream != NULL) {
     468           0 :                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
     469             :                         }
     470             :                 }
     471             : 
     472             :                 /*
     473             :                  * We need to handle the case when we get a relative open
     474             :                  * relative to a file and the pathname is blank - this is a
     475             :                  * reopen! (hint from demyn plantenberg)
     476             :                  */
     477           0 :                 return NT_STATUS_INVALID_HANDLE;
     478             :         }
     479             : 
     480         552 :         if (ISDOT(dir_fsp->fsp_name->base_name)) {
     481             :                 /*
     482             :                  * We're at the toplevel dir, the final file name
     483             :                  * must not contain ./, as this is filtered out
     484             :                  * normally by srvstr_get_path and unix_convert
     485             :                  * explicitly rejects paths containing ./.
     486             :                  */
     487           4 :                 new_path = talloc_strdup(talloc_tos(), path);
     488             :         } else {
     489             :                 /*
     490             :                  * Copy in the base directory name.
     491             :                  */
     492             : 
     493         548 :                 new_path = talloc_asprintf(talloc_tos(),
     494             :                                            "%s/%s",
     495         548 :                                            dir_fsp->fsp_name->base_name,
     496             :                                            path);
     497             :         }
     498         552 :         if (new_path == NULL) {
     499           0 :                 return NT_STATUS_NO_MEMORY;
     500             :         }
     501             : 
     502         552 :         *path_out = new_path;
     503         552 :         return NT_STATUS_OK;
     504             : }
     505             : 
     506             : /****************************************************************************
     507             :  Reply to an NT create and X call.
     508             : ****************************************************************************/
     509             : 
     510       20287 : void reply_ntcreate_and_X(struct smb_request *req)
     511             : {
     512       20287 :         connection_struct *conn = req->conn;
     513       20287 :         struct smb_filename *smb_fname = NULL;
     514       20287 :         char *fname = NULL;
     515             :         uint32_t flags;
     516             :         uint32_t access_mask;
     517             :         uint32_t file_attributes;
     518             :         uint32_t share_access;
     519             :         uint32_t create_disposition;
     520             :         uint32_t create_options;
     521             :         uint16_t root_dir_fid;
     522             :         uint64_t allocation_size;
     523             :         /* Breakout the oplock request bits so we can set the
     524             :            reply bits separately. */
     525       20287 :         uint32_t fattr=0;
     526       20287 :         off_t file_len = 0;
     527       20287 :         int info = 0;
     528       20287 :         files_struct *fsp = NULL;
     529       20287 :         char *p = NULL;
     530             :         struct timespec create_timespec;
     531             :         struct timespec c_timespec;
     532             :         struct timespec a_timespec;
     533             :         struct timespec m_timespec;
     534             :         NTSTATUS status;
     535             :         int oplock_request;
     536       20287 :         uint8_t oplock_granted = NO_OPLOCK_RETURN;
     537       20287 :         struct case_semantics_state *case_state = NULL;
     538             :         uint32_t ucf_flags;
     539       20287 :         TALLOC_CTX *ctx = talloc_tos();
     540             : 
     541       20287 :         START_PROFILE(SMBntcreateX);
     542             : 
     543       20287 :         if (req->wct < 24) {
     544           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     545           0 :                 goto out;
     546             :         }
     547             : 
     548       20287 :         flags = IVAL(req->vwv+3, 1);
     549       20287 :         access_mask = IVAL(req->vwv+7, 1);
     550       20287 :         file_attributes = IVAL(req->vwv+13, 1);
     551       20287 :         share_access = IVAL(req->vwv+15, 1);
     552       20287 :         create_disposition = IVAL(req->vwv+17, 1);
     553       20287 :         create_options = IVAL(req->vwv+19, 1);
     554       20287 :         root_dir_fid = (uint16_t)IVAL(req->vwv+5, 1);
     555             : 
     556       20287 :         allocation_size = BVAL(req->vwv+9, 1);
     557             : 
     558       20287 :         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
     559             :                             STR_TERMINATE, &status);
     560             : 
     561       20287 :         if (!NT_STATUS_IS_OK(status)) {
     562         175 :                 reply_nterror(req, status);
     563         175 :                 goto out;
     564             :         }
     565             : 
     566       20112 :         DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x "
     567             :                   "file_attributes = 0x%x, share_access = 0x%x, "
     568             :                   "create_disposition = 0x%x create_options = 0x%x "
     569             :                   "root_dir_fid = 0x%x, fname = %s\n",
     570             :                         (unsigned int)flags,
     571             :                         (unsigned int)access_mask,
     572             :                         (unsigned int)file_attributes,
     573             :                         (unsigned int)share_access,
     574             :                         (unsigned int)create_disposition,
     575             :                         (unsigned int)create_options,
     576             :                         (unsigned int)root_dir_fid,
     577             :                         fname));
     578             : 
     579             :         /*
     580             :          * we need to remove ignored bits when they come directly from the client
     581             :          * because we reuse some of them for internal stuff
     582             :          */
     583       20112 :         create_options &= ~NTCREATEX_OPTIONS_MUST_IGNORE_MASK;
     584             : 
     585             :         /*
     586             :          * If it's an IPC, use the pipe handler.
     587             :          */
     588             : 
     589       20112 :         if (IS_IPC(conn)) {
     590         368 :                 if (lp_nt_pipe_support()) {
     591         368 :                         do_ntcreate_pipe_open(conn, req);
     592         368 :                         goto out;
     593             :                 }
     594           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
     595           0 :                 goto out;
     596             :         }
     597             : 
     598       19744 :         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
     599       19744 :         if (oplock_request) {
     600         238 :                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK)
     601         238 :                         ? BATCH_OPLOCK : 0;
     602             :         }
     603             : 
     604       19744 :         if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
     605           4 :                 case_state = set_posix_case_semantics(ctx, conn);
     606           4 :                 if (!case_state) {
     607           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
     608           0 :                         goto out;
     609             :                 }
     610             :         }
     611             : 
     612       19744 :         if (root_dir_fid != 0) {
     613         552 :                 char *new_fname = NULL;
     614             : 
     615         552 :                 status = get_relative_fid_filename(conn,
     616             :                                                    req,
     617             :                                                    root_dir_fid,
     618             :                                                    fname,
     619             :                                                    &new_fname);
     620         552 :                 if (!NT_STATUS_IS_OK(status)) {
     621           0 :                         reply_nterror(req, status);
     622           0 :                         goto out;
     623             :                 }
     624         552 :                 fname = new_fname;
     625             :         }
     626             : 
     627       19744 :         ucf_flags = filename_create_ucf_flags(req, create_disposition);
     628       19744 :         status = filename_convert(ctx,
     629             :                                 conn,
     630             :                                 fname,
     631             :                                 ucf_flags,
     632             :                                 0,
     633             :                                 &smb_fname);
     634             : 
     635       19744 :         TALLOC_FREE(case_state);
     636             : 
     637       19744 :         if (!NT_STATUS_IS_OK(status)) {
     638         178 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
     639           0 :                         reply_botherror(req,
     640             :                                 NT_STATUS_PATH_NOT_COVERED,
     641             :                                 ERRSRV, ERRbadpath);
     642           0 :                         goto out;
     643             :                 }
     644         178 :                 reply_nterror(req, status);
     645         178 :                 goto out;
     646             :         }
     647             : 
     648             :         /*
     649             :          * Bug #6898 - clients using Windows opens should
     650             :          * never be able to set this attribute into the
     651             :          * VFS.
     652             :          */
     653       19566 :         file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
     654             : 
     655       19566 :         status = SMB_VFS_CREATE_FILE(
     656             :                 conn,                                   /* conn */
     657             :                 req,                                    /* req */
     658             :                 smb_fname,                              /* fname */
     659             :                 access_mask,                            /* access_mask */
     660             :                 share_access,                           /* share_access */
     661             :                 create_disposition,                     /* create_disposition*/
     662             :                 create_options,                         /* create_options */
     663             :                 file_attributes,                        /* file_attributes */
     664             :                 oplock_request,                         /* oplock_request */
     665             :                 NULL,                                   /* lease */
     666             :                 allocation_size,                        /* allocation_size */
     667             :                 0,                                      /* private_flags */
     668             :                 NULL,                                   /* sd */
     669             :                 NULL,                                   /* ea_list */
     670             :                 &fsp,                                       /* result */
     671             :                 &info,                                      /* pinfo */
     672             :                 NULL, NULL);                            /* create context */
     673             : 
     674       19566 :         if (!NT_STATUS_IS_OK(status)) {
     675        6053 :                 if (open_was_deferred(req->xconn, req->mid)) {
     676             :                         /* We have re-scheduled this call, no error. */
     677          61 :                         goto out;
     678             :                 }
     679        5992 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
     680        3177 :                         bool ok = defer_smb1_sharing_violation(req);
     681        3177 :                         if (ok) {
     682        1655 :                                 goto out;
     683             :                         }
     684             :                 }
     685        4333 :                 reply_openerror(req, status);
     686        4333 :                 goto out;
     687             :         }
     688             : 
     689             :         /* Ensure we're pointing at the correct stat struct. */
     690       13513 :         TALLOC_FREE(smb_fname);
     691       13513 :         smb_fname = fsp->fsp_name;
     692             : 
     693             :         /*
     694             :          * If the caller set the extended oplock request bit
     695             :          * and we granted one (by whatever means) - set the
     696             :          * correct bit for extended oplock reply.
     697             :          */
     698             : 
     699       13701 :         if (oplock_request &&
     700         188 :             (lp_fake_oplocks(SNUM(conn))
     701         188 :              || EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))) {
     702             : 
     703             :                 /*
     704             :                  * Exclusive oplock granted
     705             :                  */
     706             : 
     707         255 :                 if (flags & REQUEST_BATCH_OPLOCK) {
     708          92 :                         oplock_granted = BATCH_OPLOCK_RETURN;
     709             :                 } else {
     710          40 :                         oplock_granted = EXCLUSIVE_OPLOCK_RETURN;
     711             :                 }
     712       13381 :         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
     713          44 :                 oplock_granted = LEVEL_II_OPLOCK_RETURN;
     714             :         } else {
     715       13337 :                 oplock_granted = NO_OPLOCK_RETURN;
     716             :         }
     717             : 
     718       13513 :         file_len = smb_fname->st.st_ex_size;
     719             : 
     720       13513 :         if (flags & EXTENDED_RESPONSE_REQUIRED) {
     721             :                 /* This is very strange. We
     722             :                  * return 50 words, but only set
     723             :                  * the wcnt to 42 ? It's definitely
     724             :                  * what happens on the wire....
     725             :                  */
     726        1086 :                 reply_outbuf(req, 50, 0);
     727        1086 :                 SCVAL(req->outbuf,smb_wct,42);
     728             :         } else {
     729       12427 :                 reply_outbuf(req, 34, 0);
     730             :         }
     731             : 
     732       13513 :         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
     733       13513 :         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
     734             : 
     735       13513 :         p = (char *)req->outbuf + smb_vwv2;
     736             : 
     737       13513 :         SCVAL(p, 0, oplock_granted);
     738             : 
     739       13513 :         p++;
     740       13513 :         SSVAL(p,0,fsp->fnum);
     741       13513 :         p += 2;
     742       13513 :         if ((create_disposition == FILE_SUPERSEDE)
     743          30 :             && (info == FILE_WAS_OVERWRITTEN)) {
     744          16 :                 SIVAL(p,0,FILE_WAS_SUPERSEDED);
     745             :         } else {
     746       13497 :                 SIVAL(p,0,info);
     747             :         }
     748       13513 :         p += 4;
     749             : 
     750       13513 :         fattr = fdos_mode(fsp);
     751       13513 :         if (fattr == 0) {
     752           0 :                 fattr = FILE_ATTRIBUTE_NORMAL;
     753             :         }
     754             : 
     755             :         /* Create time. */
     756       13513 :         create_timespec = get_create_timespec(conn, fsp, smb_fname);
     757       13513 :         a_timespec = smb_fname->st.st_ex_atime;
     758       13513 :         m_timespec = smb_fname->st.st_ex_mtime;
     759       13513 :         c_timespec = get_change_timespec(conn, fsp, smb_fname);
     760             : 
     761       13513 :         if (lp_dos_filetime_resolution(SNUM(conn))) {
     762           0 :                 dos_filetime_timespec(&create_timespec);
     763           0 :                 dos_filetime_timespec(&a_timespec);
     764           0 :                 dos_filetime_timespec(&m_timespec);
     765           0 :                 dos_filetime_timespec(&c_timespec);
     766             :         }
     767             : 
     768       13513 :         put_long_date_full_timespec(conn->ts_res, p, &create_timespec); /* create time. */
     769       13513 :         p += 8;
     770       13513 :         put_long_date_full_timespec(conn->ts_res, p, &a_timespec); /* access time */
     771       13513 :         p += 8;
     772       13513 :         put_long_date_full_timespec(conn->ts_res, p, &m_timespec); /* write time */
     773       13513 :         p += 8;
     774       13513 :         put_long_date_full_timespec(conn->ts_res, p, &c_timespec); /* change time */
     775       13513 :         p += 8;
     776       13513 :         SIVAL(p,0,fattr); /* File Attributes. */
     777       13513 :         p += 4;
     778       13513 :         SOFF_T(p, 0, SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&smb_fname->st));
     779       13513 :         p += 8;
     780       13513 :         SOFF_T(p,0,file_len);
     781       13513 :         p += 8;
     782       13513 :         if (flags & EXTENDED_RESPONSE_REQUIRED) {
     783        1086 :                 uint16_t file_status = (NO_EAS|NO_SUBSTREAMS|NO_REPARSETAG);
     784        1086 :                 unsigned int num_streams = 0;
     785        1086 :                 struct stream_struct *streams = NULL;
     786             : 
     787        1086 :                 if (lp_ea_support(SNUM(conn))) {
     788        1086 :                         size_t num_names = 0;
     789             :                         /* Do we have any EA's ? */
     790        1086 :                         status = get_ea_names_from_fsp(
     791        1086 :                             ctx, smb_fname->fsp, NULL, &num_names);
     792        1086 :                         if (NT_STATUS_IS_OK(status) && num_names) {
     793        1082 :                                 file_status &= ~NO_EAS;
     794             :                         }
     795             :                 }
     796             : 
     797        1086 :                 status = vfs_fstreaminfo(smb_fname->fsp, ctx,
     798             :                         &num_streams, &streams);
     799             :                 /* There is always one stream, ::$DATA. */
     800        1086 :                 if (NT_STATUS_IS_OK(status) && num_streams > 1) {
     801           0 :                         file_status &= ~NO_SUBSTREAMS;
     802             :                 }
     803        1086 :                 TALLOC_FREE(streams);
     804        1086 :                 SSVAL(p,2,file_status);
     805             :         }
     806       13513 :         p += 4;
     807       13513 :         SCVAL(p,0,fsp->fsp_flags.is_directory ? 1 : 0);
     808             : 
     809       13513 :         if (flags & EXTENDED_RESPONSE_REQUIRED) {
     810        1086 :                 uint32_t perms = 0;
     811        1086 :                 p += 25;
     812        1871 :                 if (fsp->fsp_flags.is_directory ||
     813        1360 :                     fsp->fsp_flags.can_write ||
     814         371 :                     can_write_to_fsp(fsp))
     815             :                 {
     816        1047 :                         perms = FILE_GENERIC_ALL;
     817             :                 } else {
     818           0 :                         perms = FILE_GENERIC_READ|FILE_EXECUTE;
     819             :                 }
     820        1086 :                 SIVAL(p,0,perms);
     821             :         }
     822             : 
     823       13513 :         DEBUG(5,("reply_ntcreate_and_X: %s, open name = %s\n",
     824             :                 fsp_fnum_dbg(fsp), smb_fname_str_dbg(smb_fname)));
     825             : 
     826       20291 :  out:
     827       20287 :         END_PROFILE(SMBntcreateX);
     828       20287 :         return;
     829             : }
     830             : 
     831             : /****************************************************************************
     832             :  Reply to a NT_TRANSACT_CREATE call to open a pipe.
     833             : ****************************************************************************/
     834             : 
     835          24 : static void do_nt_transact_create_pipe(connection_struct *conn,
     836             :                                        struct smb_request *req,
     837             :                                        uint16_t **ppsetup, uint32_t setup_count,
     838             :                                        char **ppparams, uint32_t parameter_count,
     839             :                                        char **ppdata, uint32_t data_count)
     840             : {
     841          24 :         char *fname = NULL;
     842          24 :         char *params = *ppparams;
     843          24 :         uint16_t pnum = FNUM_FIELD_INVALID;
     844          24 :         char *p = NULL;
     845             :         NTSTATUS status;
     846             :         size_t param_len;
     847             :         uint32_t flags;
     848          24 :         TALLOC_CTX *ctx = talloc_tos();
     849             : 
     850             :         /*
     851             :          * Ensure minimum number of parameters sent.
     852             :          */
     853             : 
     854          24 :         if(parameter_count < 54) {
     855           0 :                 DEBUG(0,("do_nt_transact_create_pipe - insufficient parameters (%u)\n", (unsigned int)parameter_count));
     856           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     857           0 :                 return;
     858             :         }
     859             : 
     860          24 :         flags = IVAL(params,0);
     861             : 
     862          24 :         if (req->posix_pathnames) {
     863           0 :                 srvstr_get_path_posix(ctx,
     864             :                         params,
     865           0 :                         req->flags2,
     866             :                         &fname,
     867           0 :                         params+53,
     868           0 :                         parameter_count-53,
     869             :                         STR_TERMINATE,
     870             :                         &status);
     871             :         } else {
     872          42 :                 srvstr_get_path(ctx,
     873             :                         params,
     874          24 :                         req->flags2,
     875             :                         &fname,
     876          24 :                         params+53,
     877          24 :                         parameter_count-53,
     878             :                         STR_TERMINATE,
     879             :                         &status);
     880             :         }
     881          24 :         if (!NT_STATUS_IS_OK(status)) {
     882           0 :                 reply_nterror(req, status);
     883           0 :                 return;
     884             :         }
     885             : 
     886          24 :         nt_open_pipe(fname, conn, req, &pnum);
     887             : 
     888          24 :         if (req->outbuf) {
     889             :                 /* Error return */
     890          12 :                 return;
     891             :         }
     892             : 
     893             :         /* Realloc the size of parameters and data we will return */
     894          12 :         if (flags & EXTENDED_RESPONSE_REQUIRED) {
     895             :                 /* Extended response is 32 more byyes. */
     896           0 :                 param_len = 101;
     897             :         } else {
     898          12 :                 param_len = 69;
     899             :         }
     900          12 :         params = nttrans_realloc(ppparams, param_len);
     901          12 :         if(params == NULL) {
     902           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
     903           0 :                 return;
     904             :         }
     905             : 
     906          12 :         p = params;
     907          12 :         SCVAL(p,0,NO_OPLOCK_RETURN);
     908             : 
     909          12 :         p += 2;
     910          12 :         SSVAL(p,0,pnum);
     911          12 :         p += 2;
     912          12 :         SIVAL(p,0,FILE_WAS_OPENED);
     913          12 :         p += 8;
     914             : 
     915          12 :         p += 32;
     916          12 :         SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */
     917          12 :         p += 20;
     918             :         /* File type. */
     919          12 :         SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE);
     920             :         /* Device state. */
     921          12 :         SSVAL(p,2, 0x5FF); /* ? */
     922          12 :         p += 4;
     923             : 
     924          12 :         if (flags & EXTENDED_RESPONSE_REQUIRED) {
     925           0 :                 p += 25;
     926           0 :                 SIVAL(p,0,FILE_GENERIC_ALL);
     927             :                 /*
     928             :                  * For pipes W2K3 seems to return
     929             :                  * 0x12019B next.
     930             :                  * This is ((FILE_GENERIC_READ|FILE_GENERIC_WRITE) & ~FILE_APPEND_DATA)
     931             :                  */
     932           0 :                 SIVAL(p,4,(FILE_GENERIC_READ|FILE_GENERIC_WRITE)&~FILE_APPEND_DATA);
     933             :         }
     934             : 
     935          12 :         DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname));
     936             : 
     937             :         /* Send the required number of replies */
     938          12 :         send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0);
     939             : 
     940          12 :         return;
     941             : }
     942             : 
     943             : /*********************************************************************
     944             :  Windows seems to do canonicalization of inheritance bits. Do the
     945             :  same.
     946             : *********************************************************************/
     947             : 
     948       13280 : static void canonicalize_inheritance_bits(struct files_struct *fsp,
     949             :                                           struct security_descriptor *psd)
     950             : {
     951       13280 :         bool set_auto_inherited = false;
     952             : 
     953             :         /*
     954             :          * We need to filter out the
     955             :          * SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_AUTO_INHERIT_REQ
     956             :          * bits. If both are set we store SEC_DESC_DACL_AUTO_INHERITED
     957             :          * as this alters whether SEC_ACE_FLAG_INHERITED_ACE is set
     958             :          * when an ACE is inherited. Otherwise we zero these bits out.
     959             :          * See:
     960             :          *
     961             :          * http://social.msdn.microsoft.com/Forums/eu/os_fileservices/thread/11f77b68-731e-407d-b1b3-064750716531
     962             :          *
     963             :          * for details.
     964             :          */
     965             : 
     966       13280 :         if (!lp_acl_flag_inherited_canonicalization(SNUM(fsp->conn))) {
     967           4 :                 psd->type &= ~SEC_DESC_DACL_AUTO_INHERIT_REQ;
     968           4 :                 return;
     969             :         }
     970             : 
     971       13276 :         if ((psd->type & (SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_AUTO_INHERIT_REQ))
     972             :                         == (SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_AUTO_INHERIT_REQ)) {
     973        1370 :                 set_auto_inherited = true;
     974             :         }
     975             : 
     976       13276 :         psd->type &= ~(SEC_DESC_DACL_AUTO_INHERITED|SEC_DESC_DACL_AUTO_INHERIT_REQ);
     977       13276 :         if (set_auto_inherited) {
     978        1370 :                 psd->type |= SEC_DESC_DACL_AUTO_INHERITED;
     979             :         }
     980             : }
     981             : 
     982             : /****************************************************************************
     983             :  Internal fn to set security descriptors.
     984             : ****************************************************************************/
     985             : 
     986       13282 : NTSTATUS set_sd(files_struct *fsp, struct security_descriptor *psd,
     987             :                        uint32_t security_info_sent)
     988             : {
     989       13282 :         files_struct *sd_fsp = fsp;
     990             :         NTSTATUS status;
     991             : 
     992       13282 :         if (!CAN_WRITE(fsp->conn)) {
     993           0 :                 return NT_STATUS_ACCESS_DENIED;
     994             :         }
     995             : 
     996       13282 :         if (!lp_nt_acl_support(SNUM(fsp->conn))) {
     997           0 :                 return NT_STATUS_OK;
     998             :         }
     999             : 
    1000       13282 :         status = refuse_symlink_fsp(fsp);
    1001       13282 :         if (!NT_STATUS_IS_OK(status)) {
    1002           0 :                 DBG_DEBUG("ACL set on symlink %s denied.\n",
    1003             :                         fsp_str_dbg(fsp));
    1004           0 :                 return status;
    1005             :         }
    1006             : 
    1007       13282 :         if (psd->owner_sid == NULL) {
    1008        1883 :                 security_info_sent &= ~SECINFO_OWNER;
    1009             :         }
    1010       13282 :         if (psd->group_sid == NULL) {
    1011       11121 :                 security_info_sent &= ~SECINFO_GROUP;
    1012             :         }
    1013             : 
    1014             :         /* Ensure we have at least one thing set. */
    1015       13282 :         if ((security_info_sent & (SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL)) == 0) {
    1016             :                 /* Just like W2K3 */
    1017           0 :                 return NT_STATUS_OK;
    1018             :         }
    1019             : 
    1020             :         /* Ensure we have the rights to do this. */
    1021       13282 :         if (security_info_sent & SECINFO_OWNER) {
    1022        4611 :                 if (!(fsp->access_mask & SEC_STD_WRITE_OWNER)) {
    1023           0 :                         return NT_STATUS_ACCESS_DENIED;
    1024             :                 }
    1025             :         }
    1026             : 
    1027       13282 :         if (security_info_sent & SECINFO_GROUP) {
    1028        2121 :                 if (!(fsp->access_mask & SEC_STD_WRITE_OWNER)) {
    1029           0 :                         return NT_STATUS_ACCESS_DENIED;
    1030             :                 }
    1031             :         }
    1032             : 
    1033       13282 :         if (security_info_sent & SECINFO_DACL) {
    1034       11196 :                 if (!(fsp->access_mask & SEC_STD_WRITE_DAC)) {
    1035           2 :                         return NT_STATUS_ACCESS_DENIED;
    1036             :                 }
    1037             :                 /* Convert all the generic bits. */
    1038       11194 :                 if (psd->dacl) {
    1039       11160 :                         security_acl_map_generic(psd->dacl, &file_generic_mapping);
    1040             :                 }
    1041             :         }
    1042             : 
    1043       13280 :         if (security_info_sent & SECINFO_SACL) {
    1044           2 :                 if (!(fsp->access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
    1045           0 :                         return NT_STATUS_ACCESS_DENIED;
    1046             :                 }
    1047             :                 /*
    1048             :                  * Setting a SACL also requires WRITE_DAC.
    1049             :                  * See the smbtorture3 SMB2-SACL test.
    1050             :                  */
    1051           2 :                 if (!(fsp->access_mask & SEC_STD_WRITE_DAC)) {
    1052           0 :                         return NT_STATUS_ACCESS_DENIED;
    1053             :                 }
    1054             :                 /* Convert all the generic bits. */
    1055           2 :                 if (psd->sacl) {
    1056           2 :                         security_acl_map_generic(psd->sacl, &file_generic_mapping);
    1057             :                 }
    1058             :         }
    1059             : 
    1060       13280 :         canonicalize_inheritance_bits(fsp, psd);
    1061             : 
    1062       13280 :         if (DEBUGLEVEL >= 10) {
    1063           0 :                 DEBUG(10,("set_sd for file %s\n", fsp_str_dbg(fsp)));
    1064           0 :                 NDR_PRINT_DEBUG(security_descriptor, psd);
    1065             :         }
    1066             : 
    1067       13280 :         if (fsp->base_fsp != NULL) {
    1068             :                 /*
    1069             :                  * This is a stream handle. Use
    1070             :                  * the underlying pathref handle.
    1071             :                  */
    1072           2 :                 sd_fsp = fsp->base_fsp;
    1073             :         }
    1074       13280 :         status = SMB_VFS_FSET_NT_ACL(sd_fsp, security_info_sent, psd);
    1075             : 
    1076       13280 :         TALLOC_FREE(psd);
    1077             : 
    1078       13280 :         return status;
    1079             : }
    1080             : 
    1081             : /****************************************************************************
    1082             :  Internal fn to set security descriptors from a data blob.
    1083             : ****************************************************************************/
    1084             : 
    1085       13140 : NTSTATUS set_sd_blob(files_struct *fsp, uint8_t *data, uint32_t sd_len,
    1086             :                        uint32_t security_info_sent)
    1087             : {
    1088       13140 :         struct security_descriptor *psd = NULL;
    1089             :         NTSTATUS status;
    1090             : 
    1091       13140 :         if (sd_len == 0) {
    1092           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1093             :         }
    1094             : 
    1095       13140 :         status = unmarshall_sec_desc(talloc_tos(), data, sd_len, &psd);
    1096             : 
    1097       13140 :         if (!NT_STATUS_IS_OK(status)) {
    1098           0 :                 return status;
    1099             :         }
    1100             : 
    1101       13140 :         return set_sd(fsp, psd, security_info_sent);
    1102             : }
    1103             : 
    1104             : /****************************************************************************
    1105             :  Reply to a NT_TRANSACT_CREATE call (needs to process SD's).
    1106             : ****************************************************************************/
    1107             : 
    1108         561 : static void call_nt_transact_create(connection_struct *conn,
    1109             :                                     struct smb_request *req,
    1110             :                                     uint16_t **ppsetup, uint32_t setup_count,
    1111             :                                     char **ppparams, uint32_t parameter_count,
    1112             :                                     char **ppdata, uint32_t data_count,
    1113             :                                     uint32_t max_data_count)
    1114             : {
    1115         561 :         struct smb_filename *smb_fname = NULL;
    1116         561 :         char *fname = NULL;
    1117         561 :         char *params = *ppparams;
    1118         561 :         char *data = *ppdata;
    1119             :         /* Breakout the oplock request bits so we can set the reply bits separately. */
    1120         561 :         uint32_t fattr=0;
    1121         561 :         off_t file_len = 0;
    1122         561 :         int info = 0;
    1123         561 :         files_struct *fsp = NULL;
    1124         561 :         char *p = NULL;
    1125             :         uint32_t flags;
    1126             :         uint32_t access_mask;
    1127             :         uint32_t file_attributes;
    1128             :         uint32_t share_access;
    1129             :         uint32_t create_disposition;
    1130             :         uint32_t create_options;
    1131             :         uint32_t sd_len;
    1132         561 :         struct security_descriptor *sd = NULL;
    1133             :         uint32_t ea_len;
    1134             :         uint16_t root_dir_fid;
    1135             :         struct timespec create_timespec;
    1136             :         struct timespec c_timespec;
    1137             :         struct timespec a_timespec;
    1138             :         struct timespec m_timespec;
    1139         561 :         struct ea_list *ea_list = NULL;
    1140             :         NTSTATUS status;
    1141             :         size_t param_len;
    1142             :         uint64_t allocation_size;
    1143             :         int oplock_request;
    1144             :         uint8_t oplock_granted;
    1145         561 :         struct case_semantics_state *case_state = NULL;
    1146             :         uint32_t ucf_flags;
    1147         561 :         TALLOC_CTX *ctx = talloc_tos();
    1148             : 
    1149         561 :         DEBUG(5,("call_nt_transact_create\n"));
    1150             : 
    1151             :         /*
    1152             :          * If it's an IPC, use the pipe handler.
    1153             :          */
    1154             : 
    1155         561 :         if (IS_IPC(conn)) {
    1156          24 :                 if (lp_nt_pipe_support()) {
    1157          24 :                         do_nt_transact_create_pipe(
    1158             :                                 conn, req,
    1159             :                                 ppsetup, setup_count,
    1160             :                                 ppparams, parameter_count,
    1161             :                                 ppdata, data_count);
    1162          24 :                         goto out;
    1163             :                 }
    1164           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    1165           0 :                 goto out;
    1166             :         }
    1167             : 
    1168             :         /*
    1169             :          * Ensure minimum number of parameters sent.
    1170             :          */
    1171             : 
    1172         537 :         if(parameter_count < 54) {
    1173           0 :                 DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)parameter_count));
    1174           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1175           0 :                 goto out;
    1176             :         }
    1177             : 
    1178         537 :         flags = IVAL(params,0);
    1179         537 :         access_mask = IVAL(params,8);
    1180         537 :         file_attributes = IVAL(params,20);
    1181         537 :         share_access = IVAL(params,24);
    1182         537 :         create_disposition = IVAL(params,28);
    1183         537 :         create_options = IVAL(params,32);
    1184         537 :         sd_len = IVAL(params,36);
    1185         537 :         ea_len = IVAL(params,40);
    1186         537 :         root_dir_fid = (uint16_t)IVAL(params,4);
    1187         537 :         allocation_size = BVAL(params,12);
    1188             : 
    1189             :         /*
    1190             :          * we need to remove ignored bits when they come directly from the client
    1191             :          * because we reuse some of them for internal stuff
    1192             :          */
    1193         537 :         create_options &= ~NTCREATEX_OPTIONS_MUST_IGNORE_MASK;
    1194             : 
    1195         537 :         if (req->posix_pathnames) {
    1196           0 :                 srvstr_get_path_posix(ctx,
    1197             :                         params,
    1198           0 :                         req->flags2,
    1199             :                         &fname,
    1200           0 :                         params+53,
    1201           0 :                         parameter_count-53,
    1202             :                         STR_TERMINATE,
    1203             :                         &status);
    1204             :         } else {
    1205         994 :                 srvstr_get_path(ctx,
    1206             :                         params,
    1207         537 :                         req->flags2,
    1208             :                         &fname,
    1209         537 :                         params+53,
    1210         537 :                         parameter_count-53,
    1211             :                         STR_TERMINATE,
    1212             :                         &status);
    1213             :         }
    1214         537 :         if (!NT_STATUS_IS_OK(status)) {
    1215           0 :                 reply_nterror(req, status);
    1216           0 :                 goto out;
    1217             :         }
    1218             : 
    1219         537 :         if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
    1220           0 :                 case_state = set_posix_case_semantics(ctx, conn);
    1221           0 :                 if (!case_state) {
    1222           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    1223           0 :                         goto out;
    1224             :                 }
    1225             :         }
    1226             : 
    1227         537 :         if (root_dir_fid != 0) {
    1228           0 :                 char *new_fname = NULL;
    1229             : 
    1230           0 :                 status = get_relative_fid_filename(conn,
    1231             :                                                    req,
    1232             :                                                    root_dir_fid,
    1233             :                                                    fname,
    1234             :                                                    &new_fname);
    1235           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1236           0 :                         reply_nterror(req, status);
    1237           0 :                         goto out;
    1238             :                 }
    1239           0 :                 fname = new_fname;
    1240             :         }
    1241             : 
    1242         537 :         ucf_flags = filename_create_ucf_flags(req, create_disposition);
    1243         537 :         status = filename_convert(ctx,
    1244             :                                 conn,
    1245             :                                 fname,
    1246             :                                 ucf_flags,
    1247             :                                 0,
    1248             :                                 &smb_fname);
    1249             : 
    1250         537 :         TALLOC_FREE(case_state);
    1251             : 
    1252         537 :         if (!NT_STATUS_IS_OK(status)) {
    1253           0 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    1254           0 :                         reply_botherror(req,
    1255             :                                 NT_STATUS_PATH_NOT_COVERED,
    1256             :                                 ERRSRV, ERRbadpath);
    1257           0 :                         goto out;
    1258             :                 }
    1259           0 :                 reply_nterror(req, status);
    1260           0 :                 goto out;
    1261             :         }
    1262             : 
    1263             :         /* Ensure the data_len is correct for the sd and ea values given. */
    1264         537 :         if ((ea_len + sd_len > data_count)
    1265         537 :             || (ea_len > data_count) || (sd_len > data_count)
    1266         537 :             || (ea_len + sd_len < ea_len) || (ea_len + sd_len < sd_len)) {
    1267           0 :                 DEBUG(10, ("call_nt_transact_create - ea_len = %u, sd_len = "
    1268             :                            "%u, data_count = %u\n", (unsigned int)ea_len,
    1269             :                            (unsigned int)sd_len, (unsigned int)data_count));
    1270           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1271           0 :                 goto out;
    1272             :         }
    1273             : 
    1274         537 :         if (sd_len) {
    1275         166 :                 DEBUG(10, ("call_nt_transact_create - sd_len = %d\n",
    1276             :                            sd_len));
    1277             : 
    1278         166 :                 status = unmarshall_sec_desc(ctx, (uint8_t *)data, sd_len,
    1279             :                                              &sd);
    1280         166 :                 if (!NT_STATUS_IS_OK(status)) {
    1281           0 :                         DEBUG(10, ("call_nt_transact_create: "
    1282             :                                    "unmarshall_sec_desc failed: %s\n",
    1283             :                                    nt_errstr(status)));
    1284           0 :                         reply_nterror(req, status);
    1285           0 :                         goto out;
    1286             :                 }
    1287             :         }
    1288             : 
    1289         537 :         if (ea_len) {
    1290          15 :                 if (!lp_ea_support(SNUM(conn))) {
    1291           0 :                         DEBUG(10, ("call_nt_transact_create - ea_len = %u but "
    1292             :                                    "EA's not supported.\n",
    1293             :                                    (unsigned int)ea_len));
    1294           0 :                         reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
    1295           0 :                         goto out;
    1296             :                 }
    1297             : 
    1298          15 :                 if (ea_len < 10) {
    1299           0 :                         DEBUG(10,("call_nt_transact_create - ea_len = %u - "
    1300             :                                   "too small (should be more than 10)\n",
    1301             :                                   (unsigned int)ea_len ));
    1302           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1303           0 :                         goto out;
    1304             :                 }
    1305             : 
    1306             :                 /* We have already checked that ea_len <= data_count here. */
    1307          15 :                 ea_list = read_nttrans_ea_list(talloc_tos(), data + sd_len,
    1308             :                                                ea_len);
    1309          15 :                 if (ea_list == NULL) {
    1310           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1311           0 :                         goto out;
    1312             :                 }
    1313             : 
    1314          30 :                 if (!req->posix_pathnames &&
    1315          15 :                                 ea_list_has_invalid_name(ea_list)) {
    1316             :                         /* Realloc the size of parameters and data we will return */
    1317           5 :                         if (flags & EXTENDED_RESPONSE_REQUIRED) {
    1318             :                                 /* Extended response is 32 more byyes. */
    1319           0 :                                 param_len = 101;
    1320             :                         } else {
    1321           5 :                                 param_len = 69;
    1322             :                         }
    1323           5 :                         params = nttrans_realloc(ppparams, param_len);
    1324           5 :                         if(params == NULL) {
    1325           0 :                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    1326           0 :                                 goto out;
    1327             :                         }
    1328             : 
    1329           5 :                         memset(params, '\0', param_len);
    1330           5 :                         send_nt_replies(conn, req, STATUS_INVALID_EA_NAME,
    1331             :                                 params, param_len, NULL, 0);
    1332           4 :                         goto out;
    1333             :                 }
    1334             :         }
    1335             : 
    1336         532 :         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
    1337         532 :         if (oplock_request) {
    1338           0 :                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK)
    1339           0 :                         ? BATCH_OPLOCK : 0;
    1340             :         }
    1341             : 
    1342             :         /*
    1343             :          * Bug #6898 - clients using Windows opens should
    1344             :          * never be able to set this attribute into the
    1345             :          * VFS.
    1346             :          */
    1347         532 :         file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
    1348             : 
    1349         532 :         status = SMB_VFS_CREATE_FILE(
    1350             :                 conn,                                   /* conn */
    1351             :                 req,                                    /* req */
    1352             :                 smb_fname,                              /* fname */
    1353             :                 access_mask,                            /* access_mask */
    1354             :                 share_access,                           /* share_access */
    1355             :                 create_disposition,                     /* create_disposition*/
    1356             :                 create_options,                         /* create_options */
    1357             :                 file_attributes,                        /* file_attributes */
    1358             :                 oplock_request,                         /* oplock_request */
    1359             :                 NULL,                                   /* lease */
    1360             :                 allocation_size,                        /* allocation_size */
    1361             :                 0,                                      /* private_flags */
    1362             :                 sd,                                     /* sd */
    1363             :                 ea_list,                                /* ea_list */
    1364             :                 &fsp,                                       /* result */
    1365             :                 &info,                                      /* pinfo */
    1366             :                 NULL, NULL);                            /* create context */
    1367             : 
    1368         532 :         if(!NT_STATUS_IS_OK(status)) {
    1369         106 :                 if (open_was_deferred(req->xconn, req->mid)) {
    1370             :                         /* We have re-scheduled this call, no error. */
    1371           0 :                         return;
    1372             :                 }
    1373         106 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
    1374           0 :                         bool ok = defer_smb1_sharing_violation(req);
    1375           0 :                         if (ok) {
    1376           0 :                                 return;
    1377             :                         }
    1378             :                 }
    1379         106 :                 reply_openerror(req, status);
    1380          88 :                 goto out;
    1381             :         }
    1382             : 
    1383             :         /* Ensure we're pointing at the correct stat struct. */
    1384         426 :         TALLOC_FREE(smb_fname);
    1385         426 :         smb_fname = fsp->fsp_name;
    1386             : 
    1387             :         /*
    1388             :          * If the caller set the extended oplock request bit
    1389             :          * and we granted one (by whatever means) - set the
    1390             :          * correct bit for extended oplock reply.
    1391             :          */
    1392             : 
    1393         426 :         if (oplock_request &&
    1394           0 :             (lp_fake_oplocks(SNUM(conn))
    1395           0 :              || EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))) {
    1396             : 
    1397             :                 /*
    1398             :                  * Exclusive oplock granted
    1399             :                  */
    1400             : 
    1401           0 :                 if (flags & REQUEST_BATCH_OPLOCK) {
    1402           0 :                         oplock_granted = BATCH_OPLOCK_RETURN;
    1403             :                 } else {
    1404           0 :                         oplock_granted = EXCLUSIVE_OPLOCK_RETURN;
    1405             :                 }
    1406         426 :         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
    1407           0 :                 oplock_granted = LEVEL_II_OPLOCK_RETURN;
    1408             :         } else {
    1409         426 :                 oplock_granted = NO_OPLOCK_RETURN;
    1410             :         }
    1411             : 
    1412         426 :         file_len = smb_fname->st.st_ex_size;
    1413             : 
    1414             :         /* Realloc the size of parameters and data we will return */
    1415         426 :         if (flags & EXTENDED_RESPONSE_REQUIRED) {
    1416             :                 /* Extended response is 32 more byyes. */
    1417         152 :                 param_len = 101;
    1418             :         } else {
    1419         236 :                 param_len = 69;
    1420             :         }
    1421         426 :         params = nttrans_realloc(ppparams, param_len);
    1422         426 :         if(params == NULL) {
    1423           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    1424           0 :                 goto out;
    1425             :         }
    1426             : 
    1427         426 :         p = params;
    1428         426 :         SCVAL(p, 0, oplock_granted);
    1429             : 
    1430         426 :         p += 2;
    1431         426 :         SSVAL(p,0,fsp->fnum);
    1432         426 :         p += 2;
    1433         426 :         if ((create_disposition == FILE_SUPERSEDE)
    1434          10 :             && (info == FILE_WAS_OVERWRITTEN)) {
    1435           5 :                 SIVAL(p,0,FILE_WAS_SUPERSEDED);
    1436             :         } else {
    1437         421 :                 SIVAL(p,0,info);
    1438             :         }
    1439         426 :         p += 8;
    1440             : 
    1441         426 :         fattr = fdos_mode(fsp);
    1442         426 :         if (fattr == 0) {
    1443           0 :                 fattr = FILE_ATTRIBUTE_NORMAL;
    1444             :         }
    1445             : 
    1446             :         /* Create time. */
    1447         426 :         create_timespec = get_create_timespec(conn, fsp, smb_fname);
    1448         426 :         a_timespec = smb_fname->st.st_ex_atime;
    1449         426 :         m_timespec = smb_fname->st.st_ex_mtime;
    1450         426 :         c_timespec = get_change_timespec(conn, fsp, smb_fname);
    1451             : 
    1452         426 :         if (lp_dos_filetime_resolution(SNUM(conn))) {
    1453           0 :                 dos_filetime_timespec(&create_timespec);
    1454           0 :                 dos_filetime_timespec(&a_timespec);
    1455           0 :                 dos_filetime_timespec(&m_timespec);
    1456           0 :                 dos_filetime_timespec(&c_timespec);
    1457             :         }
    1458             : 
    1459         426 :         put_long_date_full_timespec(conn->ts_res, p, &create_timespec); /* create time. */
    1460         426 :         p += 8;
    1461         426 :         put_long_date_full_timespec(conn->ts_res, p, &a_timespec); /* access time */
    1462         426 :         p += 8;
    1463         426 :         put_long_date_full_timespec(conn->ts_res, p, &m_timespec); /* write time */
    1464         426 :         p += 8;
    1465         426 :         put_long_date_full_timespec(conn->ts_res, p, &c_timespec); /* change time */
    1466         426 :         p += 8;
    1467         426 :         SIVAL(p,0,fattr); /* File Attributes. */
    1468         426 :         p += 4;
    1469         426 :         SOFF_T(p, 0, SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st));
    1470         426 :         p += 8;
    1471         426 :         SOFF_T(p,0,file_len);
    1472         426 :         p += 8;
    1473         426 :         if (flags & EXTENDED_RESPONSE_REQUIRED) {
    1474         190 :                 uint16_t file_status = (NO_EAS|NO_SUBSTREAMS|NO_REPARSETAG);
    1475         190 :                 unsigned int num_streams = 0;
    1476         190 :                 struct stream_struct *streams = NULL;
    1477             : 
    1478         190 :                 if (lp_ea_support(SNUM(conn))) {
    1479         190 :                         size_t num_names = 0;
    1480             :                         /* Do we have any EA's ? */
    1481         190 :                         status = get_ea_names_from_fsp(
    1482         190 :                             ctx, smb_fname->fsp, NULL, &num_names);
    1483         190 :                         if (NT_STATUS_IS_OK(status) && num_names) {
    1484         190 :                                 file_status &= ~NO_EAS;
    1485             :                         }
    1486             :                 }
    1487             : 
    1488         190 :                 status = vfs_fstreaminfo(smb_fname->fsp, ctx,
    1489             :                         &num_streams, &streams);
    1490             :                 /* There is always one stream, ::$DATA. */
    1491         190 :                 if (NT_STATUS_IS_OK(status) && num_streams > 1) {
    1492           0 :                         file_status &= ~NO_SUBSTREAMS;
    1493             :                 }
    1494         190 :                 TALLOC_FREE(streams);
    1495         190 :                 SSVAL(p,2,file_status);
    1496             :         }
    1497         426 :         p += 4;
    1498         426 :         SCVAL(p,0,fsp->fsp_flags.is_directory ? 1 : 0);
    1499             : 
    1500         426 :         if (flags & EXTENDED_RESPONSE_REQUIRED) {
    1501         190 :                 uint32_t perms = 0;
    1502         190 :                 p += 25;
    1503         301 :                 if (fsp->fsp_flags.is_directory ||
    1504         148 :                     fsp->fsp_flags.can_write ||
    1505           0 :                     can_write_to_fsp(fsp))
    1506             :                 {
    1507         152 :                         perms = FILE_GENERIC_ALL;
    1508             :                 } else {
    1509           0 :                         perms = FILE_GENERIC_READ|FILE_EXECUTE;
    1510             :                 }
    1511         190 :                 SIVAL(p,0,perms);
    1512             :         }
    1513             : 
    1514         426 :         DEBUG(5,("call_nt_transact_create: open name = %s\n",
    1515             :                  smb_fname_str_dbg(smb_fname)));
    1516             : 
    1517             :         /* Send the required number of replies */
    1518         426 :         send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0);
    1519         561 :  out:
    1520         502 :         return;
    1521             : }
    1522             : 
    1523             : /****************************************************************************
    1524             :  Reply to a NT CANCEL request.
    1525             :  conn POINTER CAN BE NULL HERE !
    1526             : ****************************************************************************/
    1527             : 
    1528         986 : void reply_ntcancel(struct smb_request *req)
    1529             : {
    1530         986 :         struct smbXsrv_connection *xconn = req->xconn;
    1531         986 :         struct smbd_server_connection *sconn = req->sconn;
    1532             :         bool found;
    1533             : 
    1534             :         /*
    1535             :          * Go through and cancel any pending change notifies.
    1536             :          */
    1537             : 
    1538         986 :         START_PROFILE(SMBntcancel);
    1539         986 :         srv_cancel_sign_response(xconn);
    1540         986 :         found = remove_pending_change_notify_requests_by_mid(sconn, req->mid);
    1541         986 :         if (!found) {
    1542          64 :                 smbd_smb1_brl_finish_by_mid(sconn, req->mid);
    1543             :         }
    1544             : 
    1545         986 :         DEBUG(3,("reply_ntcancel: cancel called on mid = %llu.\n",
    1546             :                 (unsigned long long)req->mid));
    1547             : 
    1548         986 :         END_PROFILE(SMBntcancel);
    1549         986 :         return;
    1550             : }
    1551             : 
    1552             : /****************************************************************************
    1553             :  Copy a file.
    1554             : ****************************************************************************/
    1555             : 
    1556          10 : NTSTATUS copy_internals(TALLOC_CTX *ctx,
    1557             :                         connection_struct *conn,
    1558             :                         struct smb_request *req,
    1559             :                         struct smb_filename *smb_fname_src,
    1560             :                         struct smb_filename *smb_fname_dst,
    1561             :                         uint32_t attrs)
    1562             : {
    1563             :         files_struct *fsp1,*fsp2;
    1564             :         uint32_t fattr;
    1565             :         int info;
    1566          10 :         off_t ret=-1;
    1567          10 :         NTSTATUS status = NT_STATUS_OK;
    1568          10 :         struct smb_filename *parent = NULL;
    1569          10 :         struct smb_filename *pathref = NULL;
    1570             : 
    1571          10 :         if (!CAN_WRITE(conn)) {
    1572           0 :                 status = NT_STATUS_MEDIA_WRITE_PROTECTED;
    1573           0 :                 goto out;
    1574             :         }
    1575             : 
    1576             :         /* Source must already exist. */
    1577          10 :         if (!VALID_STAT(smb_fname_src->st)) {
    1578           0 :                 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
    1579           0 :                 goto out;
    1580             :         }
    1581             : 
    1582             :         /* Ensure attributes match. */
    1583          10 :         fattr = fdos_mode(smb_fname_src->fsp);
    1584          10 :         if ((fattr & ~attrs) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
    1585           0 :                 status = NT_STATUS_NO_SUCH_FILE;
    1586           0 :                 goto out;
    1587             :         }
    1588             : 
    1589             :         /* Disallow if dst file already exists. */
    1590          10 :         if (VALID_STAT(smb_fname_dst->st)) {
    1591           0 :                 status = NT_STATUS_OBJECT_NAME_COLLISION;
    1592           0 :                 goto out;
    1593             :         }
    1594             : 
    1595             :         /* No links from a directory. */
    1596          10 :         if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
    1597           0 :                 status = NT_STATUS_FILE_IS_A_DIRECTORY;
    1598           0 :                 goto out;
    1599             :         }
    1600             : 
    1601          10 :         DEBUG(10,("copy_internals: doing file copy %s to %s\n",
    1602             :                   smb_fname_str_dbg(smb_fname_src),
    1603             :                   smb_fname_str_dbg(smb_fname_dst)));
    1604             : 
    1605          10 :         status = SMB_VFS_CREATE_FILE(
    1606             :                 conn,                                   /* conn */
    1607             :                 req,                                    /* req */
    1608             :                 smb_fname_src,                          /* fname */
    1609             :                 FILE_READ_DATA|FILE_READ_ATTRIBUTES|
    1610             :                         FILE_READ_EA,                   /* access_mask */
    1611             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    1612             :                     FILE_SHARE_DELETE),
    1613             :                 FILE_OPEN,                              /* create_disposition*/
    1614             :                 0,                                      /* create_options */
    1615             :                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
    1616             :                 NO_OPLOCK,                              /* oplock_request */
    1617             :                 NULL,                                   /* lease */
    1618             :                 0,                                      /* allocation_size */
    1619             :                 0,                                      /* private_flags */
    1620             :                 NULL,                                   /* sd */
    1621             :                 NULL,                                   /* ea_list */
    1622             :                 &fsp1,                                      /* result */
    1623             :                 &info,                                      /* pinfo */
    1624             :                 NULL, NULL);                            /* create context */
    1625             : 
    1626          10 :         if (!NT_STATUS_IS_OK(status)) {
    1627           0 :                 goto out;
    1628             :         }
    1629             : 
    1630          10 :         status = SMB_VFS_CREATE_FILE(
    1631             :                 conn,                                   /* conn */
    1632             :                 req,                                    /* req */
    1633             :                 smb_fname_dst,                          /* fname */
    1634             :                 FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|
    1635             :                         FILE_WRITE_EA,                  /* access_mask */
    1636             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    1637             :                     FILE_SHARE_DELETE),
    1638             :                 FILE_CREATE,                            /* create_disposition*/
    1639             :                 0,                                      /* create_options */
    1640             :                 fattr,                                  /* file_attributes */
    1641             :                 NO_OPLOCK,                              /* oplock_request */
    1642             :                 NULL,                                   /* lease */
    1643             :                 0,                                      /* allocation_size */
    1644             :                 0,                                      /* private_flags */
    1645             :                 NULL,                                   /* sd */
    1646             :                 NULL,                                   /* ea_list */
    1647             :                 &fsp2,                                      /* result */
    1648             :                 &info,                                      /* pinfo */
    1649             :                 NULL, NULL);                            /* create context */
    1650             : 
    1651          10 :         if (!NT_STATUS_IS_OK(status)) {
    1652           0 :                 close_file(NULL, fsp1, ERROR_CLOSE);
    1653           0 :                 goto out;
    1654             :         }
    1655             : 
    1656          10 :         if (smb_fname_src->st.st_ex_size) {
    1657          10 :                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
    1658             :         }
    1659             : 
    1660             :         /*
    1661             :          * As we are opening fsp1 read-only we only expect
    1662             :          * an error on close on fsp2 if we are out of space.
    1663             :          * Thus we don't look at the error return from the
    1664             :          * close of fsp1.
    1665             :          */
    1666          10 :         close_file(NULL, fsp1, NORMAL_CLOSE);
    1667             : 
    1668             :         /* Ensure the modtime is set correctly on the destination file. */
    1669          10 :         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
    1670             : 
    1671          10 :         status = close_file(NULL, fsp2, NORMAL_CLOSE);
    1672             : 
    1673             :         /* Grrr. We have to do this as open_file_ntcreate adds FILE_ATTRIBUTE_ARCHIVE when it
    1674             :            creates the file. This isn't the correct thing to do in the copy
    1675             :            case. JRA */
    1676             : 
    1677          10 :         status = SMB_VFS_PARENT_PATHNAME(conn,
    1678             :                                          talloc_tos(),
    1679             :                                          smb_fname_dst,
    1680             :                                          &parent,
    1681             :                                          NULL);
    1682          10 :         if (!NT_STATUS_IS_OK(status)) {
    1683           0 :                 goto out;
    1684             :         }
    1685          10 :         if (smb_fname_dst->fsp == NULL) {
    1686          18 :                 status = synthetic_pathref(parent,
    1687             :                                         conn->cwd_fsp,
    1688          10 :                                         smb_fname_dst->base_name,
    1689          10 :                                         smb_fname_dst->stream_name,
    1690             :                                         NULL,
    1691             :                                         smb_fname_dst->twrp,
    1692             :                                         smb_fname_dst->flags,
    1693             :                                         &pathref);
    1694             : 
    1695             :                 /* should we handle NT_STATUS_OBJECT_NAME_NOT_FOUND specially here ???? */
    1696          10 :                 if (!NT_STATUS_IS_OK(status)) {
    1697           0 :                         TALLOC_FREE(parent);
    1698           0 :                         goto out;
    1699             :                 }
    1700          10 :                 file_set_dosmode(conn, pathref, fattr, parent, false);
    1701          10 :                 smb_fname_dst->st.st_ex_mode = pathref->st.st_ex_mode;
    1702             :         } else {
    1703           0 :                 file_set_dosmode(conn, smb_fname_dst, fattr, parent, false);
    1704             :         }
    1705          10 :         TALLOC_FREE(parent);
    1706             : 
    1707          10 :         if (ret < (off_t)smb_fname_src->st.st_ex_size) {
    1708           0 :                 status = NT_STATUS_DISK_FULL;
    1709           0 :                 goto out;
    1710             :         }
    1711          18 :  out:
    1712          10 :         if (!NT_STATUS_IS_OK(status)) {
    1713           0 :                 DEBUG(3,("copy_internals: Error %s copy file %s to %s\n",
    1714             :                         nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
    1715             :                         smb_fname_str_dbg(smb_fname_dst)));
    1716             :         }
    1717             : 
    1718          10 :         return status;
    1719             : }
    1720             : 
    1721             : /****************************************************************************
    1722             :  Reply to a NT rename request.
    1723             : ****************************************************************************/
    1724             : 
    1725       20588 : void reply_ntrename(struct smb_request *req)
    1726             : {
    1727       20588 :         connection_struct *conn = req->conn;
    1728       20588 :         struct smb_filename *smb_fname_old = NULL;
    1729       20588 :         struct smb_filename *smb_fname_new = NULL;
    1730       20588 :         char *oldname = NULL;
    1731       20588 :         char *newname = NULL;
    1732       20588 :         const char *dst_original_lcomp = NULL;
    1733             :         const char *p;
    1734             :         NTSTATUS status;
    1735       20588 :         bool dest_has_wcard = False;
    1736             :         uint32_t attrs;
    1737       20588 :         uint32_t ucf_flags_src = ucf_flags_from_smb_request(req);
    1738       20588 :         uint32_t ucf_flags_dst = ucf_flags_from_smb_request(req);
    1739             :         uint16_t rename_type;
    1740       20588 :         TALLOC_CTX *ctx = talloc_tos();
    1741       20588 :         bool stream_rename = false;
    1742             : 
    1743       20588 :         START_PROFILE(SMBntrename);
    1744             : 
    1745       20588 :         if (req->wct < 4) {
    1746           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1747           0 :                 goto out;
    1748             :         }
    1749             : 
    1750       20588 :         attrs = SVAL(req->vwv+0, 0);
    1751       20588 :         rename_type = SVAL(req->vwv+1, 0);
    1752             : 
    1753       20588 :         p = (const char *)req->buf + 1;
    1754       20588 :         p += srvstr_get_path_req(ctx, req, &oldname, p, STR_TERMINATE,
    1755             :                                        &status);
    1756       20588 :         if (!NT_STATUS_IS_OK(status)) {
    1757           0 :                 reply_nterror(req, status);
    1758           0 :                 goto out;
    1759             :         }
    1760             : 
    1761       20588 :         if (!req->posix_pathnames && ms_has_wild(oldname)) {
    1762           5 :                 reply_nterror(req, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
    1763           5 :                 goto out;
    1764             :         }
    1765             : 
    1766       20583 :         p++;
    1767       20583 :         p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
    1768             :                                        &status);
    1769       20583 :         if (!NT_STATUS_IS_OK(status)) {
    1770           0 :                 reply_nterror(req, status);
    1771           0 :                 goto out;
    1772             :         }
    1773             : 
    1774       20583 :         if (!req->posix_pathnames) {
    1775             :                 /* The newname must begin with a ':' if the
    1776             :                    oldname contains a ':'. */
    1777       20583 :                 if (strchr_m(oldname, ':')) {
    1778          16 :                         if (newname[0] != ':') {
    1779           8 :                                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1780           8 :                                 goto out;
    1781             :                         }
    1782           8 :                         stream_rename = true;
    1783             :                 }
    1784             :         }
    1785             : 
    1786             :         /*
    1787             :          * If this is a rename operation, allow wildcards and save the
    1788             :          * destination's last component.
    1789             :          */
    1790       20575 :         if (rename_type == RENAME_FLAG_RENAME) {
    1791          72 :                 ucf_flags_dst |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
    1792             :         }
    1793             : 
    1794             :         /* rename_internals() calls unix_convert(), so don't call it here. */
    1795       20575 :         status = filename_convert(ctx, conn,
    1796             :                                   oldname,
    1797             :                                   ucf_flags_src,
    1798             :                                   0,
    1799             :                                   &smb_fname_old);
    1800       20575 :         if (!NT_STATUS_IS_OK(status)) {
    1801           0 :                 if (NT_STATUS_EQUAL(status,
    1802             :                                     NT_STATUS_PATH_NOT_COVERED)) {
    1803           0 :                         reply_botherror(req,
    1804             :                                         NT_STATUS_PATH_NOT_COVERED,
    1805             :                                         ERRSRV, ERRbadpath);
    1806           0 :                         goto out;
    1807             :                 }
    1808           0 :                 reply_nterror(req, status);
    1809           0 :                 goto out;
    1810             :         }
    1811             : 
    1812             :         /* Get the last component of the destination for rename_internals(). */
    1813       20575 :         dst_original_lcomp = get_original_lcomp(ctx,
    1814             :                                         conn,
    1815             :                                         newname,
    1816             :                                         ucf_flags_dst);
    1817       20575 :         if (dst_original_lcomp == NULL) {
    1818           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    1819           0 :                 goto out;
    1820             :         }
    1821             : 
    1822       20575 :         if (!req->posix_pathnames) {
    1823       20575 :                 dest_has_wcard = ms_has_wild(dst_original_lcomp);
    1824             :         }
    1825             : 
    1826       20575 :         status = filename_convert(ctx, conn,
    1827             :                                   newname,
    1828             :                                   ucf_flags_dst,
    1829             :                                   0,
    1830             :                                   &smb_fname_new);
    1831       20575 :         if (!NT_STATUS_IS_OK(status)) {
    1832           0 :                 if (NT_STATUS_EQUAL(status,
    1833             :                                     NT_STATUS_PATH_NOT_COVERED)) {
    1834           0 :                         reply_botherror(req,
    1835             :                                         NT_STATUS_PATH_NOT_COVERED,
    1836             :                                         ERRSRV, ERRbadpath);
    1837           0 :                         goto out;
    1838             :                 }
    1839           0 :                 reply_nterror(req, status);
    1840           0 :                 goto out;
    1841             :         }
    1842             : 
    1843       20575 :         if (stream_rename) {
    1844             :                 /* smb_fname_new must be the same as smb_fname_old. */
    1845           8 :                 TALLOC_FREE(smb_fname_new->base_name);
    1846          10 :                 smb_fname_new->base_name = talloc_strdup(smb_fname_new,
    1847           8 :                                                 smb_fname_old->base_name);
    1848           8 :                 if (!smb_fname_new->base_name) {
    1849           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    1850           0 :                         goto out;
    1851             :                 }
    1852             :         }
    1853             : 
    1854       20575 :         DEBUG(3,("reply_ntrename: %s -> %s\n",
    1855             :                  smb_fname_str_dbg(smb_fname_old),
    1856             :                  smb_fname_str_dbg(smb_fname_new)));
    1857             : 
    1858       20575 :         switch(rename_type) {
    1859          72 :                 case RENAME_FLAG_RENAME:
    1860          72 :                         status = rename_internals(ctx,
    1861             :                                                 conn,
    1862             :                                                 req,
    1863             :                                                 smb_fname_old,
    1864             :                                                 NULL,
    1865             :                                                 smb_fname_new,
    1866             :                                                 dst_original_lcomp,
    1867             :                                                 attrs,
    1868             :                                                 false,
    1869             :                                                 DELETE_ACCESS);
    1870          72 :                         break;
    1871          13 :                 case RENAME_FLAG_HARD_LINK:
    1872          13 :                         if (dest_has_wcard) {
    1873             :                                 /* No wildcards. */
    1874           0 :                                 status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
    1875             :                         } else {
    1876          13 :                                 status = hardlink_internals(ctx, conn,
    1877             :                                                             req,
    1878             :                                                             false,
    1879             :                                                             smb_fname_old,
    1880             :                                                             smb_fname_new);
    1881             :                         }
    1882          12 :                         break;
    1883          10 :                 case RENAME_FLAG_COPY:
    1884          10 :                         if (dest_has_wcard) {
    1885             :                                 /* No wildcards. */
    1886           0 :                                 status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
    1887             :                         } else {
    1888          10 :                                 status = copy_internals(ctx, conn, req,
    1889             :                                                         smb_fname_old,
    1890             :                                                         smb_fname_new,
    1891             :                                                         attrs);
    1892             :                         }
    1893           8 :                         break;
    1894          10 :                 case RENAME_FLAG_MOVE_CLUSTER_INFORMATION:
    1895          10 :                         status = NT_STATUS_INVALID_PARAMETER;
    1896          10 :                         break;
    1897       20470 :                 default:
    1898       20470 :                         status = NT_STATUS_ACCESS_DENIED; /* Default error. */
    1899       20470 :                         break;
    1900             :         }
    1901             : 
    1902       20575 :         if (!NT_STATUS_IS_OK(status)) {
    1903       20528 :                 if (open_was_deferred(req->xconn, req->mid)) {
    1904             :                         /* We have re-scheduled this call. */
    1905           4 :                         goto out;
    1906             :                 }
    1907       20524 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
    1908          18 :                         bool ok = defer_smb1_sharing_violation(req);
    1909          18 :                         if (ok) {
    1910           8 :                                 goto out;
    1911             :                         }
    1912             :                 }
    1913             : 
    1914       20515 :                 reply_nterror(req, status);
    1915       20515 :                 goto out;
    1916             :         }
    1917             : 
    1918          47 :         reply_outbuf(req, 0, 0);
    1919       20589 :  out:
    1920       20588 :         END_PROFILE(SMBntrename);
    1921       20588 :         return;
    1922             : }
    1923             : 
    1924             : /****************************************************************************
    1925             :  Reply to a notify change - queue the request and
    1926             :  don't allow a directory to be opened.
    1927             : ****************************************************************************/
    1928             : 
    1929        1048 : static void smbd_smb1_notify_reply(struct smb_request *req,
    1930             :                                    NTSTATUS error_code,
    1931             :                                    uint8_t *buf, size_t len)
    1932             : {
    1933        1048 :         send_nt_replies(req->conn, req, error_code, (char *)buf, len, NULL, 0);
    1934        1048 : }
    1935             : 
    1936        1050 : static void call_nt_transact_notify_change(connection_struct *conn,
    1937             :                                            struct smb_request *req,
    1938             :                                            uint16_t **ppsetup,
    1939             :                                            uint32_t setup_count,
    1940             :                                            char **ppparams,
    1941             :                                            uint32_t parameter_count,
    1942             :                                            char **ppdata, uint32_t data_count,
    1943             :                                            uint32_t max_data_count,
    1944             :                                            uint32_t max_param_count)
    1945             : {
    1946        1050 :         uint16_t *setup = *ppsetup;
    1947             :         files_struct *fsp;
    1948             :         uint32_t filter;
    1949             :         NTSTATUS status;
    1950             :         bool recursive;
    1951             : 
    1952        1050 :         if(setup_count < 6) {
    1953           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1954           0 :                 return;
    1955             :         }
    1956             : 
    1957        1050 :         fsp = file_fsp(req, SVAL(setup,4));
    1958        1050 :         filter = IVAL(setup, 0);
    1959        1050 :         recursive = (SVAL(setup, 6) != 0) ? True : False;
    1960             : 
    1961        1050 :         DEBUG(3,("call_nt_transact_notify_change\n"));
    1962             : 
    1963        1050 :         if(!fsp) {
    1964           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
    1965           0 :                 return;
    1966             :         }
    1967             : 
    1968             :         {
    1969             :                 char *filter_string;
    1970             : 
    1971        1050 :                 if (!(filter_string = notify_filter_string(NULL, filter))) {
    1972           0 :                         reply_nterror(req,NT_STATUS_NO_MEMORY);
    1973           0 :                         return;
    1974             :                 }
    1975             : 
    1976        1050 :                 DEBUG(3,("call_nt_transact_notify_change: notify change "
    1977             :                          "called on %s, filter = %s, recursive = %d\n",
    1978             :                          fsp_str_dbg(fsp), filter_string, recursive));
    1979             : 
    1980        1050 :                 TALLOC_FREE(filter_string);
    1981             :         }
    1982             : 
    1983        1050 :         if((!fsp->fsp_flags.is_directory) || (conn != fsp->conn)) {
    1984           2 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1985           2 :                 return;
    1986             :         }
    1987             : 
    1988        1048 :         if (fsp->notify == NULL) {
    1989             : 
    1990         962 :                 status = change_notify_create(fsp,
    1991             :                                               max_param_count,
    1992             :                                               filter,
    1993             :                                               recursive);
    1994         962 :                 if (!NT_STATUS_IS_OK(status)) {
    1995           0 :                         DEBUG(10, ("change_notify_create returned %s\n",
    1996             :                                    nt_errstr(status)));
    1997           0 :                         reply_nterror(req, status);
    1998           0 :                         return;
    1999             :                 }
    2000             :         }
    2001             : 
    2002        1048 :         if (change_notify_fsp_has_changes(fsp)) {
    2003             : 
    2004             :                 /*
    2005             :                  * We've got changes pending, respond immediately
    2006             :                  */
    2007             : 
    2008             :                 /*
    2009             :                  * TODO: write a torture test to check the filtering behaviour
    2010             :                  * here.
    2011             :                  */
    2012             : 
    2013         108 :                 change_notify_reply(req,
    2014          54 :                                     NT_STATUS_OK,
    2015             :                                     max_param_count,
    2016             :                                     fsp->notify,
    2017             :                                     smbd_smb1_notify_reply);
    2018             : 
    2019             :                 /*
    2020             :                  * change_notify_reply() above has independently sent its
    2021             :                  * results
    2022             :                  */
    2023          54 :                 return;
    2024             :         }
    2025             : 
    2026             :         /*
    2027             :          * No changes pending, queue the request
    2028             :          */
    2029             : 
    2030         994 :         status = change_notify_add_request(req,
    2031             :                         max_param_count,
    2032             :                         filter,
    2033             :                         recursive, fsp,
    2034             :                         smbd_smb1_notify_reply);
    2035         994 :         if (!NT_STATUS_IS_OK(status)) {
    2036           0 :                 reply_nterror(req, status);
    2037             :         }
    2038         994 :         return;
    2039             : }
    2040             : 
    2041             : /****************************************************************************
    2042             :  Reply to an NT transact rename command.
    2043             : ****************************************************************************/
    2044             : 
    2045          10 : static void call_nt_transact_rename(connection_struct *conn,
    2046             :                                     struct smb_request *req,
    2047             :                                     uint16_t **ppsetup, uint32_t setup_count,
    2048             :                                     char **ppparams, uint32_t parameter_count,
    2049             :                                     char **ppdata, uint32_t data_count,
    2050             :                                     uint32_t max_data_count)
    2051             : {
    2052          10 :         char *params = *ppparams;
    2053          10 :         char *new_name = NULL;
    2054          10 :         files_struct *fsp = NULL;
    2055             :         NTSTATUS status;
    2056          10 :         TALLOC_CTX *ctx = talloc_tos();
    2057             : 
    2058          10 :         if(parameter_count < 5) {
    2059           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2060           0 :                 return;
    2061             :         }
    2062             : 
    2063          10 :         fsp = file_fsp(req, SVAL(params, 0));
    2064          10 :         if (!check_fsp(conn, req, fsp)) {
    2065           4 :                 return;
    2066             :         }
    2067           5 :         if (req->posix_pathnames) {
    2068           0 :                 srvstr_get_path_posix(ctx,
    2069             :                                 params,
    2070           0 :                                 req->flags2,
    2071             :                                 &new_name,
    2072           0 :                                 params+4,
    2073           0 :                                 parameter_count - 4,
    2074             :                                 STR_TERMINATE,
    2075             :                                 &status);
    2076             :         } else {
    2077           9 :                 srvstr_get_path(ctx,
    2078             :                                 params,
    2079           5 :                                 req->flags2,
    2080             :                                 &new_name,
    2081           5 :                                 params+4,
    2082           5 :                                 parameter_count - 4,
    2083             :                                 STR_TERMINATE,
    2084             :                                 &status);
    2085             :         }
    2086             : 
    2087           5 :         if (!NT_STATUS_IS_OK(status)) {
    2088           0 :                 reply_nterror(req, status);
    2089           0 :                 return;
    2090             :         }
    2091             : 
    2092             :         /*
    2093             :          * W2K3 ignores this request as the RAW-RENAME test
    2094             :          * demonstrates, so we do.
    2095             :          */
    2096           5 :         send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
    2097             : 
    2098           5 :         DEBUG(3,("nt transact rename from = %s, to = %s ignored!\n",
    2099             :                  fsp_str_dbg(fsp), new_name));
    2100             : 
    2101           4 :         return;
    2102             : }
    2103             : 
    2104             : /******************************************************************************
    2105             :  Fake up a completely empty SD.
    2106             : *******************************************************************************/
    2107             : 
    2108          12 : static NTSTATUS get_null_nt_acl(TALLOC_CTX *mem_ctx, struct security_descriptor **ppsd)
    2109             : {
    2110             :         size_t sd_size;
    2111             : 
    2112          12 :         *ppsd = make_standard_sec_desc( mem_ctx, &global_sid_World, &global_sid_World, NULL, &sd_size);
    2113          12 :         if(!*ppsd) {
    2114           0 :                 DEBUG(0,("get_null_nt_acl: Unable to malloc space for security descriptor.\n"));
    2115           0 :                 return NT_STATUS_NO_MEMORY;
    2116             :         }
    2117             : 
    2118          12 :         return NT_STATUS_OK;
    2119             : }
    2120             : 
    2121             : /****************************************************************************
    2122             :  Reply to query a security descriptor.
    2123             :  Callable from SMB1 and SMB2.
    2124             :  If it returns NT_STATUS_BUFFER_TOO_SMALL, pdata_size is initialized with
    2125             :  the required size.
    2126             : ****************************************************************************/
    2127             : 
    2128       14407 : NTSTATUS smbd_do_query_security_desc(connection_struct *conn,
    2129             :                                         TALLOC_CTX *mem_ctx,
    2130             :                                         files_struct *fsp,
    2131             :                                         uint32_t security_info_wanted,
    2132             :                                         uint32_t max_data_count,
    2133             :                                         uint8_t **ppmarshalled_sd,
    2134             :                                         size_t *psd_size)
    2135             : {
    2136             :         NTSTATUS status;
    2137       14407 :         struct security_descriptor *psd = NULL;
    2138       14407 :         TALLOC_CTX *frame = talloc_stackframe();
    2139       14407 :         bool need_to_read_sd = false;
    2140             : 
    2141             :         /*
    2142             :          * Get the permissions to return.
    2143             :          */
    2144             : 
    2145       14724 :         if ((security_info_wanted & SECINFO_SACL) &&
    2146         338 :                         !(fsp->access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
    2147           0 :                 DEBUG(10, ("Access to SACL denied.\n"));
    2148           0 :                 TALLOC_FREE(frame);
    2149           0 :                 return NT_STATUS_ACCESS_DENIED;
    2150             :         }
    2151             : 
    2152       27228 :         if ((security_info_wanted & (SECINFO_DACL|SECINFO_OWNER|SECINFO_GROUP)) &&
    2153       14393 :                         !(fsp->access_mask & SEC_STD_READ_CONTROL)) {
    2154          14 :                 DEBUG(10, ("Access to DACL, OWNER, or GROUP denied.\n"));
    2155          14 :                 TALLOC_FREE(frame);
    2156          14 :                 return NT_STATUS_ACCESS_DENIED;
    2157             :         }
    2158             : 
    2159       14393 :         status = refuse_symlink_fsp(fsp);
    2160       14393 :         if (!NT_STATUS_IS_OK(status)) {
    2161           0 :                 DBG_DEBUG("ACL get on symlink %s denied.\n",
    2162             :                         fsp_str_dbg(fsp));
    2163           0 :                 TALLOC_FREE(frame);
    2164           0 :                 return status;
    2165             :         }
    2166             : 
    2167       14393 :         if (security_info_wanted & (SECINFO_DACL|SECINFO_OWNER|
    2168             :                         SECINFO_GROUP|SECINFO_SACL)) {
    2169             :                 /* Don't return SECINFO_LABEL if anything else was
    2170             :                    requested. See bug #8458. */
    2171       14381 :                 security_info_wanted &= ~SECINFO_LABEL;
    2172             : 
    2173             :                 /*
    2174             :                  * Only query the file system SD if the caller asks
    2175             :                  * for any bits. This allows a caller to open without
    2176             :                  * READ_CONTROL but still issue a query sd. See
    2177             :                  * smb2.sdread test.
    2178             :                  */
    2179       14381 :                 need_to_read_sd = true;
    2180             :         }
    2181             : 
    2182       27214 :         if (lp_nt_acl_support(SNUM(conn)) &&
    2183       27214 :             ((security_info_wanted & SECINFO_LABEL) == 0) &&
    2184             :             need_to_read_sd)
    2185       14381 :         {
    2186       14381 :                 files_struct *sd_fsp = fsp;
    2187       14381 :                 if (fsp->base_fsp != NULL) {
    2188             :                         /*
    2189             :                          * This is a stream handle. Use
    2190             :                          * the underlying pathref handle.
    2191             :                          */
    2192           4 :                         sd_fsp = fsp->base_fsp;
    2193             :                 }
    2194       14381 :                 status = SMB_VFS_FGET_NT_ACL(
    2195             :                         sd_fsp, security_info_wanted, frame, &psd);
    2196             :         } else {
    2197          12 :                 status = get_null_nt_acl(frame, &psd);
    2198             :         }
    2199             : 
    2200       14393 :         if (!NT_STATUS_IS_OK(status)) {
    2201           0 :                 TALLOC_FREE(frame);
    2202           0 :                 return status;
    2203             :         }
    2204             : 
    2205       14393 :         if (!(security_info_wanted & SECINFO_OWNER)) {
    2206        1270 :                 psd->owner_sid = NULL;
    2207             :         }
    2208       14393 :         if (!(security_info_wanted & SECINFO_GROUP)) {
    2209       10680 :                 psd->group_sid = NULL;
    2210             :         }
    2211       14393 :         if (!(security_info_wanted & SECINFO_DACL)) {
    2212          18 :                 psd->type &= ~SEC_DESC_DACL_PRESENT;
    2213          18 :                 psd->dacl = NULL;
    2214             :         }
    2215       14393 :         if (!(security_info_wanted & SECINFO_SACL)) {
    2216       14055 :                 psd->type &= ~SEC_DESC_SACL_PRESENT;
    2217       14055 :                 psd->sacl = NULL;
    2218             :         }
    2219             : 
    2220             :         /* If the SACL/DACL is NULL, but was requested, we mark that it is
    2221             :          * present in the reply to match Windows behavior */
    2222       27212 :         if (psd->sacl == NULL &&
    2223       14391 :             security_info_wanted & SECINFO_SACL)
    2224         336 :                 psd->type |= SEC_DESC_SACL_PRESENT;
    2225       14422 :         if (psd->dacl == NULL &&
    2226          36 :             security_info_wanted & SECINFO_DACL)
    2227          18 :                 psd->type |= SEC_DESC_DACL_PRESENT;
    2228             : 
    2229       14393 :         if (security_info_wanted & SECINFO_LABEL) {
    2230             :                 /* Like W2K3 return a null object. */
    2231           0 :                 psd->owner_sid = NULL;
    2232           0 :                 psd->group_sid = NULL;
    2233           0 :                 psd->dacl = NULL;
    2234           0 :                 psd->sacl = NULL;
    2235           0 :                 psd->type &= ~(SEC_DESC_DACL_PRESENT|SEC_DESC_SACL_PRESENT);
    2236             :         }
    2237             : 
    2238       14393 :         *psd_size = ndr_size_security_descriptor(psd, 0);
    2239             : 
    2240       14393 :         DEBUG(3,("smbd_do_query_security_desc: sd_size = %lu.\n",
    2241             :                 (unsigned long)*psd_size));
    2242             : 
    2243       14393 :         if (DEBUGLEVEL >= 10) {
    2244           0 :                 DEBUG(10,("smbd_do_query_security_desc for file %s\n",
    2245             :                           fsp_str_dbg(fsp)));
    2246           0 :                 NDR_PRINT_DEBUG(security_descriptor, psd);
    2247             :         }
    2248             : 
    2249       14393 :         if (max_data_count < *psd_size) {
    2250           8 :                 TALLOC_FREE(frame);
    2251           8 :                 return NT_STATUS_BUFFER_TOO_SMALL;
    2252             :         }
    2253             : 
    2254       14385 :         status = marshall_sec_desc(mem_ctx, psd,
    2255             :                                    ppmarshalled_sd, psd_size);
    2256             : 
    2257       14385 :         if (!NT_STATUS_IS_OK(status)) {
    2258           0 :                 TALLOC_FREE(frame);
    2259           0 :                 return status;
    2260             :         }
    2261             : 
    2262       14385 :         TALLOC_FREE(frame);
    2263       14385 :         return NT_STATUS_OK;
    2264             : }
    2265             : 
    2266             : /****************************************************************************
    2267             :  SMB1 reply to query a security descriptor.
    2268             : ****************************************************************************/
    2269             : 
    2270        7306 : static void call_nt_transact_query_security_desc(connection_struct *conn,
    2271             :                                                  struct smb_request *req,
    2272             :                                                  uint16_t **ppsetup,
    2273             :                                                  uint32_t setup_count,
    2274             :                                                  char **ppparams,
    2275             :                                                  uint32_t parameter_count,
    2276             :                                                  char **ppdata,
    2277             :                                                  uint32_t data_count,
    2278             :                                                  uint32_t max_data_count)
    2279             : {
    2280        7306 :         char *params = *ppparams;
    2281        7306 :         char *data = *ppdata;
    2282        7306 :         size_t sd_size = 0;
    2283             :         uint32_t security_info_wanted;
    2284        7306 :         files_struct *fsp = NULL;
    2285             :         NTSTATUS status;
    2286        7306 :         uint8_t *marshalled_sd = NULL;
    2287             : 
    2288        7306 :         if(parameter_count < 8) {
    2289           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2290           0 :                 return;
    2291             :         }
    2292             : 
    2293        7306 :         fsp = file_fsp(req, SVAL(params,0));
    2294        7306 :         if(!fsp) {
    2295           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
    2296           0 :                 return;
    2297             :         }
    2298             : 
    2299        7306 :         security_info_wanted = IVAL(params,4);
    2300             : 
    2301        7306 :         DEBUG(3,("call_nt_transact_query_security_desc: file = %s, "
    2302             :                  "info_wanted = 0x%x\n", fsp_str_dbg(fsp),
    2303             :                  (unsigned int)security_info_wanted));
    2304             : 
    2305        7306 :         params = nttrans_realloc(ppparams, 4);
    2306        7306 :         if(params == NULL) {
    2307           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    2308           0 :                 return;
    2309             :         }
    2310             : 
    2311             :         /*
    2312             :          * Get the permissions to return.
    2313             :          */
    2314             : 
    2315        7306 :         status = smbd_do_query_security_desc(conn,
    2316             :                                         talloc_tos(),
    2317             :                                         fsp,
    2318             :                                         security_info_wanted &
    2319             :                                         SMB_SUPPORTED_SECINFO_FLAGS,
    2320             :                                         max_data_count,
    2321             :                                         &marshalled_sd,
    2322             :                                         &sd_size);
    2323             : 
    2324        7306 :         if (NT_STATUS_EQUAL(status, NT_STATUS_BUFFER_TOO_SMALL)) {
    2325           0 :                 SIVAL(params,0,(uint32_t)sd_size);
    2326           0 :                 send_nt_replies(conn, req, NT_STATUS_BUFFER_TOO_SMALL,
    2327             :                         params, 4, NULL, 0);
    2328           0 :                 return;
    2329             :         }
    2330             : 
    2331        7306 :         if (!NT_STATUS_IS_OK(status)) {
    2332           0 :                 reply_nterror(req, status);
    2333           0 :                 return;
    2334             :         }
    2335             : 
    2336        7306 :         SMB_ASSERT(sd_size > 0);
    2337             : 
    2338        7306 :         SIVAL(params,0,(uint32_t)sd_size);
    2339             : 
    2340        7306 :         if (max_data_count < sd_size) {
    2341           0 :                 send_nt_replies(conn, req, NT_STATUS_BUFFER_TOO_SMALL,
    2342             :                                 params, 4, NULL, 0);
    2343           0 :                 return;
    2344             :         }
    2345             : 
    2346             :         /*
    2347             :          * Allocate the data we will return.
    2348             :          */
    2349             : 
    2350        7306 :         data = nttrans_realloc(ppdata, sd_size);
    2351        7306 :         if(data == NULL) {
    2352           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    2353           0 :                 return;
    2354             :         }
    2355             : 
    2356        7306 :         memcpy(data, marshalled_sd, sd_size);
    2357             : 
    2358        7306 :         send_nt_replies(conn, req, NT_STATUS_OK, params, 4, data, (int)sd_size);
    2359             : 
    2360        7306 :         return;
    2361             : }
    2362             : 
    2363             : /****************************************************************************
    2364             :  Reply to set a security descriptor. Map to UNIX perms or POSIX ACLs.
    2365             : ****************************************************************************/
    2366             : 
    2367        6594 : static void call_nt_transact_set_security_desc(connection_struct *conn,
    2368             :                                                struct smb_request *req,
    2369             :                                                uint16_t **ppsetup,
    2370             :                                                uint32_t setup_count,
    2371             :                                                char **ppparams,
    2372             :                                                uint32_t parameter_count,
    2373             :                                                char **ppdata,
    2374             :                                                uint32_t data_count,
    2375             :                                                uint32_t max_data_count)
    2376             : {
    2377        6594 :         char *params= *ppparams;
    2378        6594 :         char *data = *ppdata;
    2379        6594 :         files_struct *fsp = NULL;
    2380        6594 :         uint32_t security_info_sent = 0;
    2381             :         NTSTATUS status;
    2382             : 
    2383        6594 :         if(parameter_count < 8) {
    2384           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2385           0 :                 return;
    2386             :         }
    2387             : 
    2388        6594 :         if((fsp = file_fsp(req, SVAL(params,0))) == NULL) {
    2389          18 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
    2390          18 :                 return;
    2391             :         }
    2392             : 
    2393        6576 :         if (!CAN_WRITE(fsp->conn)) {
    2394           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    2395           0 :                 return;
    2396             :         }
    2397             : 
    2398        6576 :         if(!lp_nt_acl_support(SNUM(conn))) {
    2399           0 :                 goto done;
    2400             :         }
    2401             : 
    2402        6576 :         security_info_sent = IVAL(params,4);
    2403             : 
    2404        6576 :         DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n",
    2405             :                  fsp_str_dbg(fsp), (unsigned int)security_info_sent));
    2406             : 
    2407        6576 :         if (data_count == 0) {
    2408           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2409           0 :                 return;
    2410             :         }
    2411             : 
    2412        6576 :         status = set_sd_blob(fsp, (uint8_t *)data, data_count,
    2413             :                              security_info_sent & SMB_SUPPORTED_SECINFO_FLAGS);
    2414        6576 :         if (!NT_STATUS_IS_OK(status)) {
    2415           0 :                 reply_nterror(req, status);
    2416           0 :                 return;
    2417             :         }
    2418             : 
    2419        6576 :   done:
    2420        6576 :         send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
    2421        6576 :         return;
    2422             : }
    2423             : 
    2424             : /****************************************************************************
    2425             :  Reply to NT IOCTL
    2426             : ****************************************************************************/
    2427             : 
    2428        1342 : static void call_nt_transact_ioctl(connection_struct *conn,
    2429             :                                    struct smb_request *req,
    2430             :                                    uint16_t **ppsetup, uint32_t setup_count,
    2431             :                                    char **ppparams, uint32_t parameter_count,
    2432             :                                    char **ppdata, uint32_t data_count,
    2433             :                                    uint32_t max_data_count)
    2434             : {
    2435             :         NTSTATUS status;
    2436             :         uint32_t function;
    2437             :         uint16_t fidnum;
    2438             :         files_struct *fsp;
    2439             :         uint8_t isFSctl;
    2440             :         uint8_t compfilter;
    2441        1342 :         char *out_data = NULL;
    2442        1342 :         uint32_t out_data_len = 0;
    2443        1342 :         char *pdata = *ppdata;
    2444        1342 :         TALLOC_CTX *ctx = talloc_tos();
    2445             : 
    2446        1342 :         if (setup_count != 8) {
    2447           0 :                 DEBUG(3,("call_nt_transact_ioctl: invalid setup count %d\n", setup_count));
    2448           0 :                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
    2449           0 :                 return;
    2450             :         }
    2451             : 
    2452        1342 :         function = IVAL(*ppsetup, 0);
    2453        1342 :         fidnum = SVAL(*ppsetup, 4);
    2454        1342 :         isFSctl = CVAL(*ppsetup, 6);
    2455        1342 :         compfilter = CVAL(*ppsetup, 7);
    2456             : 
    2457        1342 :         DEBUG(10, ("call_nt_transact_ioctl: function[0x%08X] FID[0x%04X] isFSctl[0x%02X] compfilter[0x%02X]\n", 
    2458             :                  function, fidnum, isFSctl, compfilter));
    2459             : 
    2460        1342 :         fsp=file_fsp(req, fidnum);
    2461             : 
    2462             :         /*
    2463             :          * We don't really implement IOCTLs, especially on files.
    2464             :          */
    2465        1342 :         if (!isFSctl) {
    2466           0 :                 DEBUG(10, ("isFSctl: 0x%02X indicates IOCTL, not FSCTL!\n",
    2467             :                         isFSctl));
    2468           0 :                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
    2469           0 :                 return;
    2470             :         }
    2471             : 
    2472             :         /* Has to be for an open file! */
    2473        1342 :         if (!check_fsp_open(conn, req, fsp)) {
    2474           0 :                 return;
    2475             :         }
    2476             : 
    2477        1342 :         SMB_PERFCOUNT_SET_IOCTL(&req->pcd, function);
    2478             : 
    2479             :         /*
    2480             :          * out_data might be allocated by the VFS module, but talloc should be
    2481             :          * used, and should be cleaned up when the request ends.
    2482             :          */
    2483        1342 :         status = SMB_VFS_FSCTL(fsp, 
    2484             :                                ctx,
    2485             :                                function, 
    2486             :                                req->flags2,
    2487             :                                (uint8_t *)pdata, 
    2488             :                                data_count, 
    2489             :                                (uint8_t **)&out_data,
    2490             :                                max_data_count,
    2491             :                                &out_data_len);
    2492        1342 :         if (!NT_STATUS_IS_OK(status)) {
    2493          74 :                 reply_nterror(req, status);
    2494             :         } else {
    2495        1268 :                 send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, out_data, out_data_len);
    2496             :         }
    2497             : }
    2498             : 
    2499             : 
    2500             : #ifdef HAVE_SYS_QUOTAS
    2501          12 : static enum ndr_err_code fill_qtlist_from_sids(TALLOC_CTX *mem_ctx,
    2502             :                                                struct files_struct *fsp,
    2503             :                                                SMB_NTQUOTA_HANDLE *qt_handle,
    2504             :                                                struct dom_sid *sids,
    2505             :                                                uint32_t elems)
    2506             : {
    2507             :         uint32_t i;
    2508          12 :         TALLOC_CTX *list_ctx = NULL;
    2509             : 
    2510          12 :         list_ctx = talloc_init("quota_sid_list");
    2511             : 
    2512          12 :         if (list_ctx == NULL) {
    2513           0 :                 DBG_ERR("failed to allocate\n");
    2514           0 :                 return NDR_ERR_ALLOC;
    2515             :         }
    2516             : 
    2517          12 :         if (qt_handle->quota_list!=NULL) {
    2518           0 :                 free_ntquota_list(&(qt_handle->quota_list));
    2519             :         }
    2520          24 :         for (i = 0; i < elems; i++) {
    2521             :                 SMB_NTQUOTA_STRUCT qt;
    2522             :                 SMB_NTQUOTA_LIST *list_item;
    2523             :                 bool ok;
    2524             : 
    2525          12 :                 if (!NT_STATUS_IS_OK(vfs_get_ntquota(fsp,
    2526             :                                                      SMB_USER_QUOTA_TYPE,
    2527             :                                                      &sids[i], &qt))) {
    2528             :                         /* non fatal error, return empty item in result */
    2529           0 :                         ZERO_STRUCT(qt);
    2530           0 :                         continue;
    2531             :                 }
    2532             : 
    2533             : 
    2534          12 :                 list_item = talloc_zero(list_ctx, SMB_NTQUOTA_LIST);
    2535          12 :                 if (list_item == NULL) {
    2536           0 :                         DBG_ERR("failed to allocate\n");
    2537           0 :                         return NDR_ERR_ALLOC;
    2538             :                 }
    2539             : 
    2540          12 :                 ok = sid_to_uid(&sids[i], &list_item->uid);
    2541          12 :                 if (!ok) {
    2542             :                         struct dom_sid_buf buf;
    2543           0 :                         DBG_WARNING("Could not convert SID %s to uid\n",
    2544             :                                     dom_sid_str_buf(&sids[i], &buf));
    2545             :                         /* No idea what to return here... */
    2546           0 :                         return NDR_ERR_INVALID_POINTER;
    2547             :                 }
    2548             : 
    2549          12 :                 list_item->quotas = talloc_zero(list_item, SMB_NTQUOTA_STRUCT);
    2550          12 :                 if (list_item->quotas == NULL) {
    2551           0 :                         DBG_ERR("failed to allocate\n");
    2552           0 :                         return NDR_ERR_ALLOC;
    2553             :                 }
    2554             : 
    2555          12 :                 *list_item->quotas = qt;
    2556          12 :                 list_item->mem_ctx = list_ctx;
    2557          12 :                 DLIST_ADD(qt_handle->quota_list, list_item);
    2558             :         }
    2559          12 :         qt_handle->tmp_list = qt_handle->quota_list;
    2560          12 :         return NDR_ERR_SUCCESS;
    2561             : }
    2562             : 
    2563          12 : static enum ndr_err_code extract_sids_from_buf(TALLOC_CTX *mem_ctx,
    2564             :                                   uint32_t sidlistlength,
    2565             :                                   DATA_BLOB *sid_buf,
    2566             :                                   struct dom_sid **sids,
    2567             :                                   uint32_t *num)
    2568             : {
    2569             :         DATA_BLOB blob;
    2570          12 :         uint32_t i = 0;
    2571             :         enum ndr_err_code err;
    2572             : 
    2573             :         struct sid_list_elem {
    2574             :                 struct sid_list_elem *prev, *next;
    2575             :                 struct dom_sid sid;
    2576             :         };
    2577             : 
    2578          12 :         struct sid_list_elem *sid_list = NULL;
    2579          12 :         struct sid_list_elem *iter = NULL;
    2580          12 :         TALLOC_CTX *list_ctx = talloc_init("sid_list");
    2581          12 :         if (!list_ctx) {
    2582           0 :                 DBG_ERR("OOM\n");
    2583           0 :                 err = NDR_ERR_ALLOC;
    2584           0 :                 goto done;
    2585             :         }
    2586             : 
    2587          12 :         *num = 0;
    2588          12 :         *sids = NULL;
    2589             : 
    2590          12 :         if (sidlistlength) {
    2591          12 :                 uint32_t offset = 0;
    2592          12 :                 struct ndr_pull *ndr_pull = NULL;
    2593             : 
    2594          12 :                 if (sidlistlength > sid_buf->length) {
    2595           0 :                         DBG_ERR("sid_list_length 0x%x exceeds "
    2596             :                                 "available bytes %zx\n",
    2597             :                                 sidlistlength,
    2598             :                                 sid_buf->length);
    2599           0 :                         err = NDR_ERR_OFFSET;
    2600           0 :                         goto done;
    2601             :                 }
    2602           0 :                 while (true) {
    2603             :                         struct file_get_quota_info info;
    2604          12 :                         struct sid_list_elem *item = NULL;
    2605          12 :                         uint32_t new_offset = 0;
    2606          12 :                         blob.data = sid_buf->data + offset;
    2607          12 :                         blob.length = sidlistlength - offset;
    2608          12 :                         ndr_pull = ndr_pull_init_blob(&blob, list_ctx);
    2609          12 :                         if (!ndr_pull) {
    2610           0 :                                 DBG_ERR("OOM\n");
    2611           0 :                                 err = NDR_ERR_ALLOC;
    2612           0 :                                 goto done;
    2613             :                         }
    2614          12 :                         err = ndr_pull_file_get_quota_info(ndr_pull,
    2615             :                                            NDR_SCALARS | NDR_BUFFERS, &info);
    2616          12 :                         if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
    2617           0 :                                 DBG_ERR("Failed to pull file_get_quota_info "
    2618             :                                         "from sidlist buffer\n");
    2619           0 :                                 goto done;
    2620             :                         }
    2621          12 :                         item = talloc_zero(list_ctx, struct sid_list_elem);
    2622          12 :                         if (!item) {
    2623           0 :                                 DBG_ERR("OOM\n");
    2624           0 :                                 err = NDR_ERR_ALLOC;
    2625           0 :                                 goto done;
    2626             :                         }
    2627          12 :                         item->sid = info.sid;
    2628          12 :                         DLIST_ADD(sid_list, item);
    2629          12 :                         i++;
    2630          12 :                         if (i == UINT32_MAX) {
    2631           0 :                                 DBG_ERR("Integer overflow\n");
    2632           0 :                                 err = NDR_ERR_ARRAY_SIZE;
    2633           0 :                                 goto done;
    2634             :                         }
    2635          12 :                         new_offset = info.next_entry_offset;
    2636             : 
    2637             :                         /* if new_offset == 0 no more sid(s) to read. */
    2638          12 :                         if (new_offset == 0) {
    2639          12 :                                 break;
    2640             :                         }
    2641             : 
    2642             :                         /* Integer wrap? */
    2643           0 :                         if ((offset + new_offset) < offset) {
    2644           0 :                                 DBG_ERR("Integer wrap while adding "
    2645             :                                         "new_offset 0x%x to current "
    2646             :                                         "buffer offset 0x%x\n",
    2647             :                                         new_offset, offset);
    2648           0 :                                 err = NDR_ERR_OFFSET;
    2649           0 :                                 goto done;
    2650             :                         }
    2651             : 
    2652           0 :                         offset += new_offset;
    2653             : 
    2654             :                         /* check if new offset is outside buffer boundry. */
    2655           0 :                         if (offset >= sidlistlength) {
    2656           0 :                                 DBG_ERR("bufsize 0x%x exceeded by "
    2657             :                                         "new offset 0x%x)\n",
    2658             :                                         sidlistlength,
    2659             :                                         offset);
    2660           0 :                                 err = NDR_ERR_OFFSET;
    2661           0 :                                 goto done;
    2662             :                         }
    2663             :                 }
    2664          12 :                 *sids = talloc_zero_array(mem_ctx, struct dom_sid, i);
    2665          12 :                 if (*sids == NULL) {
    2666           0 :                         DBG_ERR("OOM\n");
    2667           0 :                         err = NDR_ERR_ALLOC;
    2668           0 :                         goto done;
    2669             :                 }
    2670             : 
    2671          12 :                 *num = i;
    2672             : 
    2673          24 :                 for (iter = sid_list, i = 0; iter; iter = iter->next, i++) {
    2674             :                         struct dom_sid_buf buf;
    2675          12 :                         (*sids)[i] = iter->sid;
    2676          12 :                         DBG_DEBUG("quota SID[%u] %s\n",
    2677             :                                 (unsigned int)i,
    2678             :                                 dom_sid_str_buf(&iter->sid, &buf));
    2679             :                 }
    2680             :         }
    2681          12 :         err = NDR_ERR_SUCCESS;
    2682          12 : done:
    2683          12 :         TALLOC_FREE(list_ctx);
    2684          12 :         return err;
    2685             : }
    2686             : 
    2687          20 : NTSTATUS smbd_do_query_getinfo_quota(TALLOC_CTX *mem_ctx,
    2688             :                                      files_struct *fsp,
    2689             :                                      bool restart_scan,
    2690             :                                      bool return_single,
    2691             :                                      uint32_t sid_list_length,
    2692             :                                      DATA_BLOB *sid_buf,
    2693             :                                      uint32_t max_data_count,
    2694             :                                      uint8_t **p_data,
    2695             :                                      uint32_t *p_data_size)
    2696             : {
    2697             :         NTSTATUS status;
    2698          20 :         SMB_NTQUOTA_HANDLE *qt_handle = NULL;
    2699          20 :         SMB_NTQUOTA_LIST *qt_list = NULL;
    2700          20 :         DATA_BLOB blob = data_blob_null;
    2701             :         enum ndr_err_code err;
    2702             : 
    2703          20 :         qt_handle =
    2704          20 :                 (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->private_data;
    2705             : 
    2706          20 :         if (sid_list_length ) {
    2707             :                 struct dom_sid *sids;
    2708          12 :                 uint32_t elems = 0;
    2709             :                 /*
    2710             :                  * error check pulled offsets and lengths for wrap and
    2711             :                  * exceeding available bytes.
    2712             :                  */
    2713          12 :                 if (sid_list_length > sid_buf->length) {
    2714           0 :                         DBG_ERR("sid_list_length 0x%x exceeds "
    2715             :                                 "available bytes %zx\n",
    2716             :                                 sid_list_length,
    2717             :                                 sid_buf->length);
    2718           0 :                         return NT_STATUS_INVALID_PARAMETER;
    2719             :                 }
    2720             : 
    2721          12 :                 err = extract_sids_from_buf(mem_ctx, sid_list_length,
    2722             :                                             sid_buf, &sids, &elems);
    2723          12 :                 if (!NDR_ERR_CODE_IS_SUCCESS(err) || elems == 0) {
    2724           0 :                         return NT_STATUS_INVALID_PARAMETER;
    2725             :                 }
    2726          12 :                 err = fill_qtlist_from_sids(mem_ctx,
    2727             :                                             fsp,
    2728             :                                             qt_handle,
    2729             :                                             sids,
    2730             :                                             elems);
    2731          12 :                 if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
    2732           0 :                         return NT_STATUS_INVALID_PARAMETER;
    2733             :                 }
    2734           8 :         } else if (restart_scan) {
    2735           4 :                 if (vfs_get_user_ntquota_list(fsp,
    2736             :                                               &(qt_handle->quota_list))!=0) {
    2737           0 :                         return NT_STATUS_INTERNAL_ERROR;
    2738             :                 }
    2739             :         } else {
    2740           8 :                 if (qt_handle->quota_list!=NULL &&
    2741           4 :                         qt_handle->tmp_list==NULL) {
    2742           4 :                         free_ntquota_list(&(qt_handle->quota_list));
    2743             :                 }
    2744             :         }
    2745             : 
    2746          20 :         if (restart_scan !=0 ) {
    2747           4 :                 qt_list = qt_handle->quota_list;
    2748             :         } else {
    2749          16 :                 qt_list = qt_handle->tmp_list;
    2750             :         }
    2751          20 :         status = fill_quota_buffer(mem_ctx, qt_list,
    2752             :                                    return_single != 0,
    2753             :                                    max_data_count,
    2754             :                                    &blob,
    2755             :                                    &qt_handle->tmp_list);
    2756          20 :         if (!NT_STATUS_IS_OK(status)) {
    2757           4 :                 return status;
    2758             :         }
    2759          16 :         if (blob.length > max_data_count) {
    2760           0 :                 return NT_STATUS_BUFFER_TOO_SMALL;
    2761             :         }
    2762             : 
    2763          16 :         *p_data = blob.data;
    2764          16 :         *p_data_size = blob.length;
    2765          16 :         return NT_STATUS_OK;
    2766             : }
    2767             : 
    2768             : /****************************************************************************
    2769             :  Reply to get user quota
    2770             : ****************************************************************************/
    2771             : 
    2772           2 : static void call_nt_transact_get_user_quota(connection_struct *conn,
    2773             :                                             struct smb_request *req,
    2774             :                                             uint16_t **ppsetup,
    2775             :                                             uint32_t setup_count,
    2776             :                                             char **ppparams,
    2777             :                                             uint32_t parameter_count,
    2778             :                                             char **ppdata,
    2779             :                                             uint32_t data_count,
    2780             :                                             uint32_t max_data_count)
    2781             : {
    2782           2 :         const struct loadparm_substitution *lp_sub =
    2783           0 :                 loadparm_s3_global_substitution();
    2784           2 :         NTSTATUS nt_status = NT_STATUS_OK;
    2785           2 :         char *params = *ppparams;
    2786           2 :         char *pdata = *ppdata;
    2787           2 :         int data_len = 0;
    2788           2 :         int param_len = 0;
    2789           2 :         files_struct *fsp = NULL;
    2790           2 :         DATA_BLOB blob = data_blob_null;
    2791           2 :         struct nttrans_query_quota_params info = {0};
    2792             :         enum ndr_err_code err;
    2793           2 :         TALLOC_CTX *tmp_ctx = NULL;
    2794           2 :         uint32_t resp_len = 0;
    2795           2 :         uint8_t *resp_data = 0;
    2796             : 
    2797           2 :         tmp_ctx = talloc_init("ntquota_list");
    2798           2 :         if (!tmp_ctx) {
    2799           0 :                 nt_status = NT_STATUS_NO_MEMORY;
    2800           0 :                 goto error;
    2801             :         }
    2802             : 
    2803             :         /* access check */
    2804           2 :         if (get_current_uid(conn) != sec_initial_uid()) {
    2805           0 :                 DEBUG(1,("get_user_quota: access_denied service [%s] user "
    2806             :                          "[%s]\n", lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
    2807             :                          conn->session_info->unix_info->unix_name));
    2808           0 :                 nt_status = NT_STATUS_ACCESS_DENIED;
    2809           0 :                 goto error;
    2810             :         }
    2811             : 
    2812           2 :         blob.data = (uint8_t*)params;
    2813           2 :         blob.length = parameter_count;
    2814             : 
    2815           2 :         err = ndr_pull_struct_blob(&blob, tmp_ctx, &info,
    2816             :                 (ndr_pull_flags_fn_t)ndr_pull_nttrans_query_quota_params);
    2817             : 
    2818           2 :         if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
    2819           0 :                 DEBUG(0,("TRANSACT_GET_USER_QUOTA: failed to pull "
    2820             :                          "query_quota_params."));
    2821           0 :                 nt_status = NT_STATUS_INVALID_PARAMETER;
    2822           0 :                 goto error;
    2823             :         }
    2824           2 :         DBG_DEBUG("info.return_single_entry = %u, info.restart_scan = %u, "
    2825             :                   "info.sid_list_length = %u, info.start_sid_length = %u, "
    2826             :                   "info.start_sid_offset = %u\n",
    2827             :                   (unsigned int)info.return_single_entry,
    2828             :                   (unsigned int)info.restart_scan,
    2829             :                   (unsigned int)info.sid_list_length,
    2830             :                   (unsigned int)info.start_sid_length,
    2831             :                   (unsigned int)info.start_sid_offset);
    2832             : 
    2833             :         /* set blob to point at data for further parsing */
    2834           2 :         blob.data = (uint8_t*)pdata;
    2835           2 :         blob.length = data_count;
    2836             :         /*
    2837             :          * Although MS-SMB ref is ambiguous here, a microsoft client will
    2838             :          * only ever send a start sid (as part of a list) with
    2839             :          * sid_list_length & start_sid_offset both set to the actual list
    2840             :          * length. Note: Only a single result is returned in this case
    2841             :          * In the case where either start_sid_offset or start_sid_length
    2842             :          * are set alone or if both set (but have different values) then
    2843             :          * it seems windows will return a number of entries from the start
    2844             :          * of the list of users with quotas set. This behaviour is undocumented
    2845             :          * and windows clients do not send messages of that type. As such we
    2846             :          * currently will reject these requests.
    2847             :          */
    2848           2 :         if (info.start_sid_length
    2849           2 :         || (info.sid_list_length != info.start_sid_offset)) {
    2850           0 :                 DBG_ERR("TRANSACT_GET_USER_QUOTA: unsupported single or "
    2851             :                         "compound sid format\n");
    2852           0 :                 nt_status = NT_STATUS_INVALID_PARAMETER;
    2853           0 :                 goto error;
    2854             :         }
    2855             : 
    2856             :         /* maybe we can check the quota_fnum */
    2857           2 :         fsp = file_fsp(req, info.fid);
    2858           2 :         if (!check_fsp_ntquota_handle(conn, req, fsp)) {
    2859           0 :                 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
    2860           0 :                 nt_status = NT_STATUS_INVALID_HANDLE;
    2861           0 :                 goto error;
    2862             :         }
    2863           6 :         nt_status = smbd_do_query_getinfo_quota(tmp_ctx,
    2864             :                                   fsp,
    2865           2 :                                   info.restart_scan,
    2866           2 :                                   info.return_single_entry,
    2867             :                                   info.sid_list_length,
    2868             :                                   &blob,
    2869             :                                   max_data_count,
    2870             :                                   &resp_data,
    2871             :                                   &resp_len);
    2872           2 :         if (!NT_STATUS_IS_OK(nt_status)) {
    2873           0 :                 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MORE_ENTRIES)) {
    2874           0 :                         goto error;
    2875             :                 }
    2876           0 :                 nt_status = NT_STATUS_OK;
    2877             :         }
    2878             : 
    2879           2 :         param_len = 4;
    2880           2 :         params = nttrans_realloc(ppparams, param_len);
    2881           2 :         if(params == NULL) {
    2882           0 :                 nt_status = NT_STATUS_NO_MEMORY;
    2883           0 :                 goto error;
    2884             :         }
    2885             : 
    2886           2 :         data_len = resp_len;
    2887           2 :         SIVAL(params, 0, data_len);
    2888           2 :         pdata = nttrans_realloc(ppdata, data_len);
    2889           2 :         memcpy(pdata, resp_data, data_len);
    2890             : 
    2891           2 :         TALLOC_FREE(tmp_ctx);
    2892           2 :         send_nt_replies(conn, req, nt_status, params, param_len,
    2893             :                         pdata, data_len);
    2894           2 :         return;
    2895           0 : error:
    2896           0 :         TALLOC_FREE(tmp_ctx);
    2897           0 :         reply_nterror(req, nt_status);
    2898             : }
    2899             : 
    2900             : /****************************************************************************
    2901             :  Reply to set user quota
    2902             : ****************************************************************************/
    2903             : 
    2904           0 : static void call_nt_transact_set_user_quota(connection_struct *conn,
    2905             :                                             struct smb_request *req,
    2906             :                                             uint16_t **ppsetup,
    2907             :                                             uint32_t setup_count,
    2908             :                                             char **ppparams,
    2909             :                                             uint32_t parameter_count,
    2910             :                                             char **ppdata,
    2911             :                                             uint32_t data_count,
    2912             :                                             uint32_t max_data_count)
    2913             : {
    2914           0 :         const struct loadparm_substitution *lp_sub =
    2915           0 :                 loadparm_s3_global_substitution();
    2916           0 :         char *params = *ppparams;
    2917           0 :         char *pdata = *ppdata;
    2918           0 :         int data_len=0,param_len=0;
    2919             :         SMB_NTQUOTA_STRUCT qt;
    2920           0 :         struct file_quota_information info = {0};
    2921             :         enum ndr_err_code err;
    2922             :         struct dom_sid sid;
    2923             :         DATA_BLOB inblob;
    2924           0 :         files_struct *fsp = NULL;
    2925           0 :         TALLOC_CTX *ctx = NULL;
    2926           0 :         NTSTATUS status = NT_STATUS_OK;
    2927           0 :         ZERO_STRUCT(qt);
    2928             : 
    2929             :         /* access check */
    2930           0 :         if (get_current_uid(conn) != sec_initial_uid()) {
    2931           0 :                 DEBUG(1,("set_user_quota: access_denied service [%s] user "
    2932             :                          "[%s]\n", lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
    2933             :                          conn->session_info->unix_info->unix_name));
    2934           0 :                 status = NT_STATUS_ACCESS_DENIED;
    2935           0 :                 goto error;
    2936             :         }
    2937             : 
    2938             :         /*
    2939             :          * Ensure minimum number of parameters sent.
    2940             :          */
    2941             : 
    2942           0 :         if (parameter_count < 2) {
    2943           0 :                 DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= 2 bytes parameters\n",parameter_count));
    2944           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    2945           0 :                 goto error;
    2946             :         }
    2947             : 
    2948             :         /* maybe we can check the quota_fnum */
    2949           0 :         fsp = file_fsp(req, SVAL(params,0));
    2950           0 :         if (!check_fsp_ntquota_handle(conn, req, fsp)) {
    2951           0 :                 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
    2952           0 :                 status = NT_STATUS_INVALID_HANDLE;
    2953           0 :                 goto error;
    2954             :         }
    2955             : 
    2956           0 :         ctx = talloc_init("set_user_quota");
    2957           0 :         if (!ctx) {
    2958           0 :                 status = NT_STATUS_NO_MEMORY;
    2959           0 :                 goto error;
    2960             :         }
    2961           0 :         inblob.data = (uint8_t*)pdata;
    2962           0 :         inblob.length = data_count;
    2963             : 
    2964           0 :         err = ndr_pull_struct_blob(
    2965             :                         &inblob,
    2966             :                         ctx,
    2967             :                         &info,
    2968             :                         (ndr_pull_flags_fn_t)ndr_pull_file_quota_information);
    2969             : 
    2970           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
    2971           0 :                 DEBUG(0,("TRANSACT_SET_USER_QUOTA: failed to pull "
    2972             :                          "file_quota_information\n"));
    2973           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    2974           0 :                 goto error;
    2975             :         }
    2976           0 :         qt.usedspace = info.quota_used;
    2977             : 
    2978           0 :         qt.softlim = info.quota_threshold;
    2979             : 
    2980           0 :         qt.hardlim = info.quota_limit;
    2981             : 
    2982           0 :         sid = info.sid;
    2983             : 
    2984           0 :         if (vfs_set_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &qt)!=0) {
    2985           0 :                 status = NT_STATUS_INTERNAL_ERROR;
    2986           0 :                 goto error;
    2987             :         }
    2988             : 
    2989           0 :         send_nt_replies(conn, req, NT_STATUS_OK, params, param_len,
    2990             :                         pdata, data_len);
    2991           0 :         TALLOC_FREE(ctx);
    2992           0 :         return;
    2993           0 : error:
    2994           0 :         TALLOC_FREE(ctx);
    2995           0 :         reply_nterror(req, status);
    2996             : }
    2997             : #endif /* HAVE_SYS_QUOTAS */
    2998             : 
    2999       16865 : static void handle_nttrans(connection_struct *conn,
    3000             :                            struct trans_state *state,
    3001             :                            struct smb_request *req)
    3002             : {
    3003       16865 :         if (get_Protocol() >= PROTOCOL_NT1) {
    3004       16865 :                 req->flags2 |= 0x40; /* IS_LONG_NAME */
    3005       16865 :                 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_flg2,req->flags2);
    3006             :         }
    3007             : 
    3008             : 
    3009       16865 :         SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
    3010             : 
    3011             :         /* Now we must call the relevant NT_TRANS function */
    3012       16865 :         switch(state->call) {
    3013         561 :                 case NT_TRANSACT_CREATE:
    3014             :                 {
    3015         561 :                         START_PROFILE(NT_transact_create);
    3016        1511 :                         call_nt_transact_create(
    3017             :                                 conn, req,
    3018             :                                 &state->setup, state->setup_count,
    3019         561 :                                 &state->param, state->total_param,
    3020         561 :                                 &state->data, state->total_data,
    3021             :                                 state->max_data_return);
    3022         561 :                         END_PROFILE(NT_transact_create);
    3023         502 :                         break;
    3024             :                 }
    3025             : 
    3026        1342 :                 case NT_TRANSACT_IOCTL:
    3027             :                 {
    3028        1342 :                         START_PROFILE(NT_transact_ioctl);
    3029        4018 :                         call_nt_transact_ioctl(
    3030             :                                 conn, req,
    3031             :                                 &state->setup, state->setup_count,
    3032        1342 :                                 &state->param, state->total_param,
    3033        1342 :                                 &state->data, state->total_data,
    3034             :                                 state->max_data_return);
    3035        1342 :                         END_PROFILE(NT_transact_ioctl);
    3036        1338 :                         break;
    3037             :                 }
    3038             : 
    3039        6594 :                 case NT_TRANSACT_SET_SECURITY_DESC:
    3040             :                 {
    3041        6594 :                         START_PROFILE(NT_transact_set_security_desc);
    3042       18718 :                         call_nt_transact_set_security_desc(
    3043             :                                 conn, req,
    3044             :                                 &state->setup, state->setup_count,
    3045        6594 :                                 &state->param, state->total_param,
    3046        6594 :                                 &state->data, state->total_data,
    3047             :                                 state->max_data_return);
    3048        6594 :                         END_PROFILE(NT_transact_set_security_desc);
    3049        6594 :                         break;
    3050             :                 }
    3051             : 
    3052        1050 :                 case NT_TRANSACT_NOTIFY_CHANGE:
    3053             :                 {
    3054        1050 :                         START_PROFILE(NT_transact_notify_change);
    3055        3150 :                         call_nt_transact_notify_change(
    3056             :                                 conn, req,
    3057             :                                 &state->setup, state->setup_count,
    3058        1050 :                                 &state->param, state->total_param,
    3059        1050 :                                 &state->data, state->total_data,
    3060             :                                 state->max_data_return,
    3061             :                                 state->max_param_return);
    3062        1050 :                         END_PROFILE(NT_transact_notify_change);
    3063        1050 :                         break;
    3064             :                 }
    3065             : 
    3066          10 :                 case NT_TRANSACT_RENAME:
    3067             :                 {
    3068          10 :                         START_PROFILE(NT_transact_rename);
    3069          26 :                         call_nt_transact_rename(
    3070             :                                 conn, req,
    3071             :                                 &state->setup, state->setup_count,
    3072          10 :                                 &state->param, state->total_param,
    3073          10 :                                 &state->data, state->total_data,
    3074             :                                 state->max_data_return);
    3075          10 :                         END_PROFILE(NT_transact_rename);
    3076           8 :                         break;
    3077             :                 }
    3078             : 
    3079        7306 :                 case NT_TRANSACT_QUERY_SECURITY_DESC:
    3080             :                 {
    3081        7306 :                         START_PROFILE(NT_transact_query_security_desc);
    3082       20776 :                         call_nt_transact_query_security_desc(
    3083             :                                 conn, req,
    3084             :                                 &state->setup, state->setup_count,
    3085        7306 :                                 &state->param, state->total_param,
    3086        7306 :                                 &state->data, state->total_data,
    3087             :                                 state->max_data_return);
    3088        7306 :                         END_PROFILE(NT_transact_query_security_desc);
    3089        7306 :                         break;
    3090             :                 }
    3091             : 
    3092             : #ifdef HAVE_SYS_QUOTAS
    3093           2 :                 case NT_TRANSACT_GET_USER_QUOTA:
    3094             :                 {
    3095           2 :                         START_PROFILE(NT_transact_get_user_quota);
    3096           6 :                         call_nt_transact_get_user_quota(
    3097             :                                 conn, req,
    3098             :                                 &state->setup, state->setup_count,
    3099           2 :                                 &state->param, state->total_param,
    3100           2 :                                 &state->data, state->total_data,
    3101             :                                 state->max_data_return);
    3102           2 :                         END_PROFILE(NT_transact_get_user_quota);
    3103           2 :                         break;
    3104             :                 }
    3105             : 
    3106           0 :                 case NT_TRANSACT_SET_USER_QUOTA:
    3107             :                 {
    3108           0 :                         START_PROFILE(NT_transact_set_user_quota);
    3109           0 :                         call_nt_transact_set_user_quota(
    3110             :                                 conn, req,
    3111             :                                 &state->setup, state->setup_count,
    3112           0 :                                 &state->param, state->total_param,
    3113           0 :                                 &state->data, state->total_data,
    3114             :                                 state->max_data_return);
    3115           0 :                         END_PROFILE(NT_transact_set_user_quota);
    3116           0 :                         break;
    3117             :                 }
    3118             : #endif /* HAVE_SYS_QUOTAS */
    3119             : 
    3120           0 :                 default:
    3121             :                         /* Error in request */
    3122           0 :                         DEBUG(0,("handle_nttrans: Unknown request %d in "
    3123             :                                  "nttrans call\n", state->call));
    3124           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    3125           0 :                         return;
    3126             :         }
    3127       16800 :         return;
    3128             : }
    3129             : 
    3130             : /****************************************************************************
    3131             :  Reply to a SMBNTtrans.
    3132             : ****************************************************************************/
    3133             : 
    3134       16865 : void reply_nttrans(struct smb_request *req)
    3135             : {
    3136       16865 :         connection_struct *conn = req->conn;
    3137             :         uint32_t pscnt;
    3138             :         uint32_t psoff;
    3139             :         uint32_t dscnt;
    3140             :         uint32_t dsoff;
    3141             :         uint16_t function_code;
    3142             :         NTSTATUS result;
    3143             :         struct trans_state *state;
    3144             : 
    3145       16865 :         START_PROFILE(SMBnttrans);
    3146             : 
    3147       16865 :         if (req->wct < 19) {
    3148           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    3149           0 :                 END_PROFILE(SMBnttrans);
    3150           0 :                 return;
    3151             :         }
    3152             : 
    3153       16865 :         pscnt = IVAL(req->vwv+9, 1);
    3154       16865 :         psoff = IVAL(req->vwv+11, 1);
    3155       16865 :         dscnt = IVAL(req->vwv+13, 1);
    3156       16865 :         dsoff = IVAL(req->vwv+15, 1);
    3157       16865 :         function_code = SVAL(req->vwv+18, 0);
    3158             : 
    3159       16865 :         if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) {
    3160           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    3161           0 :                 END_PROFILE(SMBnttrans);
    3162           0 :                 return;
    3163             :         }
    3164             : 
    3165       16865 :         result = allow_new_trans(conn->pending_trans, req->mid);
    3166       16865 :         if (!NT_STATUS_IS_OK(result)) {
    3167           0 :                 DEBUG(2, ("Got invalid nttrans request: %s\n", nt_errstr(result)));
    3168           0 :                 reply_nterror(req, result);
    3169           0 :                 END_PROFILE(SMBnttrans);
    3170           0 :                 return;
    3171             :         }
    3172             : 
    3173       16865 :         if ((state = talloc(conn, struct trans_state)) == NULL) {
    3174           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    3175           0 :                 END_PROFILE(SMBnttrans);
    3176           0 :                 return;
    3177             :         }
    3178             : 
    3179       16865 :         state->cmd = SMBnttrans;
    3180             : 
    3181       16865 :         state->mid = req->mid;
    3182       16865 :         state->vuid = req->vuid;
    3183       16865 :         state->total_data = IVAL(req->vwv+3, 1);
    3184       16865 :         state->data = NULL;
    3185       16865 :         state->total_param = IVAL(req->vwv+1, 1);
    3186       16865 :         state->param = NULL;
    3187       16865 :         state->max_data_return = IVAL(req->vwv+7, 1);
    3188       16865 :         state->max_param_return = IVAL(req->vwv+5, 1);
    3189             : 
    3190             :         /* setup count is in *words* */
    3191       16865 :         state->setup_count = 2*CVAL(req->vwv+17, 1);
    3192       16865 :         state->setup = NULL;
    3193       16865 :         state->call = function_code;
    3194             : 
    3195       16865 :         DEBUG(10, ("num_setup=%u, "
    3196             :                    "param_total=%u, this_param=%u, max_param=%u, "
    3197             :                    "data_total=%u, this_data=%u, max_data=%u, "
    3198             :                    "param_offset=%u, data_offset=%u\n",
    3199             :                    (unsigned)state->setup_count,
    3200             :                    (unsigned)state->total_param, (unsigned)pscnt,
    3201             :                    (unsigned)state->max_param_return,
    3202             :                    (unsigned)state->total_data, (unsigned)dscnt,
    3203             :                    (unsigned)state->max_data_return,
    3204             :                    (unsigned)psoff, (unsigned)dsoff));
    3205             : 
    3206             :         /*
    3207             :          * All nttrans messages we handle have smb_wct == 19 +
    3208             :          * state->setup_count.  Ensure this is so as a sanity check.
    3209             :          */
    3210             : 
    3211       16865 :         if(req->wct != 19 + (state->setup_count/2)) {
    3212           0 :                 DEBUG(2,("Invalid smb_wct %d in nttrans call (should be %d)\n",
    3213             :                          req->wct, 19 + (state->setup_count/2)));
    3214           0 :                 goto bad_param;
    3215             :         }
    3216             : 
    3217             :         /* Don't allow more than 128mb for each value. */
    3218       32535 :         if ((state->total_data > (1024*1024*128)) ||
    3219       16865 :             (state->total_param > (1024*1024*128))) {
    3220           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    3221           0 :                 END_PROFILE(SMBnttrans);
    3222           0 :                 return;
    3223             :         }
    3224             : 
    3225       16865 :         if ((dscnt > state->total_data) || (pscnt > state->total_param))
    3226           0 :                 goto bad_param;
    3227             : 
    3228       16865 :         if (state->total_data)  {
    3229             : 
    3230        6789 :                 if (trans_oob(state->total_data, 0, dscnt)
    3231        6789 :                     || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
    3232           0 :                         goto bad_param;
    3233             :                 }
    3234             : 
    3235             :                 /* Can't use talloc here, the core routines do realloc on the
    3236             :                  * params and data. */
    3237        6789 :                 if ((state->data = (char *)SMB_MALLOC(state->total_data)) == NULL) {
    3238           0 :                         DEBUG(0,("reply_nttrans: data malloc fail for %u "
    3239             :                                  "bytes !\n", (unsigned int)state->total_data));
    3240           0 :                         TALLOC_FREE(state);
    3241           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    3242           0 :                         END_PROFILE(SMBnttrans);
    3243           0 :                         return;
    3244             :                 }
    3245             : 
    3246        6789 :                 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
    3247             :         }
    3248             : 
    3249       16865 :         if (state->total_param) {
    3250             : 
    3251       14473 :                 if (trans_oob(state->total_param, 0, pscnt)
    3252       14473 :                     || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
    3253           0 :                         goto bad_param;
    3254             :                 }
    3255             : 
    3256             :                 /* Can't use talloc here, the core routines do realloc on the
    3257             :                  * params and data. */
    3258       14473 :                 if ((state->param = (char *)SMB_MALLOC(state->total_param)) == NULL) {
    3259           0 :                         DEBUG(0,("reply_nttrans: param malloc fail for %u "
    3260             :                                  "bytes !\n", (unsigned int)state->total_param));
    3261           0 :                         SAFE_FREE(state->data);
    3262           0 :                         TALLOC_FREE(state);
    3263           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    3264           0 :                         END_PROFILE(SMBnttrans);
    3265           0 :                         return;
    3266             :                 }
    3267             : 
    3268       14473 :                 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
    3269             :         }
    3270             : 
    3271       16865 :         state->received_data  = dscnt;
    3272       16865 :         state->received_param = pscnt;
    3273             : 
    3274       16865 :         if(state->setup_count > 0) {
    3275        2394 :                 DEBUG(10,("reply_nttrans: state->setup_count = %d\n",
    3276             :                           state->setup_count));
    3277             : 
    3278             :                 /*
    3279             :                  * No overflow possible here, state->setup_count is an
    3280             :                  * unsigned int, being filled by a single byte from
    3281             :                  * CVAL(req->vwv+13, 0) above. The cast in the comparison
    3282             :                  * below is not necessary, it's here to clarify things. The
    3283             :                  * validity of req->vwv and req->wct has been checked in
    3284             :                  * init_smb_request already.
    3285             :                  */
    3286        2394 :                 if ((state->setup_count/2) + 19 > (unsigned int)req->wct) {
    3287           0 :                         goto bad_param;
    3288             :                 }
    3289             : 
    3290        2394 :                 state->setup = (uint16_t *)TALLOC(state, state->setup_count);
    3291        2394 :                 if (state->setup == NULL) {
    3292           0 :                         DEBUG(0,("reply_nttrans : Out of memory\n"));
    3293           0 :                         SAFE_FREE(state->data);
    3294           0 :                         SAFE_FREE(state->param);
    3295           0 :                         TALLOC_FREE(state);
    3296           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    3297           0 :                         END_PROFILE(SMBnttrans);
    3298           0 :                         return;
    3299             :                 }
    3300             : 
    3301        2398 :                 memcpy(state->setup, req->vwv+19, state->setup_count);
    3302        2394 :                 dump_data(10, (uint8_t *)state->setup, state->setup_count);
    3303             :         }
    3304             : 
    3305       32535 :         if ((state->received_data == state->total_data) &&
    3306       16865 :             (state->received_param == state->total_param)) {
    3307       16865 :                 handle_nttrans(conn, state, req);
    3308       16865 :                 SAFE_FREE(state->param);
    3309       16865 :                 SAFE_FREE(state->data);
    3310       16865 :                 TALLOC_FREE(state);
    3311       16865 :                 END_PROFILE(SMBnttrans);
    3312       16800 :                 return;
    3313             :         }
    3314             : 
    3315           0 :         DLIST_ADD(conn->pending_trans, state);
    3316             : 
    3317             :         /* We need to send an interim response then receive the rest
    3318             :            of the parameter/data bytes */
    3319           0 :         reply_outbuf(req, 0, 0);
    3320           0 :         show_msg((char *)req->outbuf);
    3321           0 :         END_PROFILE(SMBnttrans);
    3322           0 :         return;
    3323             : 
    3324           0 :   bad_param:
    3325             : 
    3326           0 :         DEBUG(0,("reply_nttrans: invalid trans parameters\n"));
    3327           0 :         SAFE_FREE(state->data);
    3328           0 :         SAFE_FREE(state->param);
    3329           0 :         TALLOC_FREE(state);
    3330           0 :         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    3331           0 :         END_PROFILE(SMBnttrans);
    3332           0 :         return;
    3333             : }
    3334             : 
    3335             : /****************************************************************************
    3336             :  Reply to a SMBnttranss
    3337             :  ****************************************************************************/
    3338             : 
    3339           0 : void reply_nttranss(struct smb_request *req)
    3340             : {
    3341           0 :         connection_struct *conn = req->conn;
    3342             :         uint32_t pcnt,poff,dcnt,doff,pdisp,ddisp;
    3343             :         struct trans_state *state;
    3344             : 
    3345           0 :         START_PROFILE(SMBnttranss);
    3346             : 
    3347           0 :         show_msg((const char *)req->inbuf);
    3348             : 
    3349             :         /* Windows clients expect all replies to
    3350             :            an NT transact secondary (SMBnttranss 0xA1)
    3351             :            to have a command code of NT transact
    3352             :            (SMBnttrans 0xA0). See bug #8989 for details. */
    3353           0 :         req->cmd = SMBnttrans;
    3354             : 
    3355           0 :         if (req->wct < 18) {
    3356           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    3357           0 :                 END_PROFILE(SMBnttranss);
    3358           0 :                 return;
    3359             :         }
    3360             : 
    3361           0 :         for (state = conn->pending_trans; state != NULL;
    3362           0 :              state = state->next) {
    3363           0 :                 if (state->mid == req->mid) {
    3364           0 :                         break;
    3365             :                 }
    3366             :         }
    3367             : 
    3368           0 :         if ((state == NULL) || (state->cmd != SMBnttrans)) {
    3369           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    3370           0 :                 END_PROFILE(SMBnttranss);
    3371           0 :                 return;
    3372             :         }
    3373             : 
    3374             :         /* Revise state->total_param and state->total_data in case they have
    3375             :            changed downwards */
    3376           0 :         if (IVAL(req->vwv+1, 1) < state->total_param) {
    3377           0 :                 state->total_param = IVAL(req->vwv+1, 1);
    3378             :         }
    3379           0 :         if (IVAL(req->vwv+3, 1) < state->total_data) {
    3380           0 :                 state->total_data = IVAL(req->vwv+3, 1);
    3381             :         }
    3382             : 
    3383           0 :         pcnt = IVAL(req->vwv+5, 1);
    3384           0 :         poff = IVAL(req->vwv+7, 1);
    3385           0 :         pdisp = IVAL(req->vwv+9, 1);
    3386             : 
    3387           0 :         dcnt = IVAL(req->vwv+11, 1);
    3388           0 :         doff = IVAL(req->vwv+13, 1);
    3389           0 :         ddisp = IVAL(req->vwv+15, 1);
    3390             : 
    3391           0 :         state->received_param += pcnt;
    3392           0 :         state->received_data += dcnt;
    3393             : 
    3394           0 :         if ((state->received_data > state->total_data) ||
    3395           0 :             (state->received_param > state->total_param))
    3396           0 :                 goto bad_param;
    3397             : 
    3398           0 :         if (pcnt) {
    3399           0 :                 if (trans_oob(state->total_param, pdisp, pcnt)
    3400           0 :                     || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
    3401           0 :                         goto bad_param;
    3402             :                 }
    3403           0 :                 memcpy(state->param+pdisp, smb_base(req->inbuf)+poff,pcnt);
    3404             :         }
    3405             : 
    3406           0 :         if (dcnt) {
    3407           0 :                 if (trans_oob(state->total_data, ddisp, dcnt)
    3408           0 :                     || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
    3409           0 :                         goto bad_param;
    3410             :                 }
    3411           0 :                 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
    3412             :         }
    3413             : 
    3414           0 :         if ((state->received_param < state->total_param) ||
    3415           0 :             (state->received_data < state->total_data)) {
    3416           0 :                 END_PROFILE(SMBnttranss);
    3417           0 :                 return;
    3418             :         }
    3419             : 
    3420           0 :         handle_nttrans(conn, state, req);
    3421             : 
    3422           0 :         DLIST_REMOVE(conn->pending_trans, state);
    3423           0 :         SAFE_FREE(state->data);
    3424           0 :         SAFE_FREE(state->param);
    3425           0 :         TALLOC_FREE(state);
    3426           0 :         END_PROFILE(SMBnttranss);
    3427           0 :         return;
    3428             : 
    3429           0 :   bad_param:
    3430             : 
    3431           0 :         DEBUG(0,("reply_nttranss: invalid trans parameters\n"));
    3432           0 :         DLIST_REMOVE(conn->pending_trans, state);
    3433           0 :         SAFE_FREE(state->data);
    3434           0 :         SAFE_FREE(state->param);
    3435           0 :         TALLOC_FREE(state);
    3436           0 :         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    3437           0 :         END_PROFILE(SMBnttranss);
    3438           0 :         return;
    3439             : }

Generated by: LCOV version 1.13