LCOV - code coverage report
Current view: top level - source3/smbd - pipes.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 154 254 60.6 %
Date: 2021-08-25 13:27:56 Functions: 6 8 75.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Pipe SMB reply routines
       4             :    Copyright (C) Andrew Tridgell 1992-1998
       5             :    Copyright (C) Luke Kenneth Casson Leighton 1996-1998
       6             :    Copyright (C) Paul Ashton  1997-1998.
       7             :    Copyright (C) Jeremy Allison 2005.
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : /*
      23             :    This file handles reply_ calls on named pipes that the server
      24             :    makes to handle specific protocols
      25             : */
      26             : 
      27             : 
      28             : #include "includes.h"
      29             : #include "smbd/smbd.h"
      30             : #include "smbd/globals.h"
      31             : #include "libcli/security/security.h"
      32             : #include "rpc_server/srv_pipe_hnd.h"
      33             : #include "auth/auth_util.h"
      34             : #include "librpc/rpc/dcerpc_helper.h"
      35             : 
      36       16477 : NTSTATUS open_np_file(struct smb_request *smb_req, const char *name,
      37             :                       struct files_struct **pfsp)
      38             : {
      39       16477 :         struct smbXsrv_connection *xconn = smb_req->xconn;
      40       16477 :         struct connection_struct *conn = smb_req->conn;
      41             :         struct files_struct *fsp;
      42       16477 :         struct smb_filename *smb_fname = NULL;
      43       16477 :         struct auth_session_info *session_info = conn->session_info;
      44             :         NTSTATUS status;
      45             : 
      46       16477 :         status = file_new(smb_req, conn, &fsp);
      47       16477 :         if (!NT_STATUS_IS_OK(status)) {
      48           0 :                 DEBUG(0, ("file_new failed: %s\n", nt_errstr(status)));
      49           0 :                 return status;
      50             :         }
      51             : 
      52       16477 :         fsp->conn = conn;
      53       16477 :         fsp_set_fd(fsp, -1);
      54       16477 :         fsp->vuid = smb_req->vuid;
      55       16477 :         fsp->fsp_flags.can_lock = false;
      56       16477 :         fsp->access_mask = FILE_READ_DATA | FILE_WRITE_DATA;
      57             : 
      58       16477 :         smb_fname = synthetic_smb_fname(talloc_tos(),
      59             :                                         name,
      60             :                                         NULL,
      61             :                                         NULL,
      62             :                                         0,
      63             :                                         0);
      64       16477 :         if (smb_fname == NULL) {
      65           0 :                 file_free(smb_req, fsp);
      66           0 :                 return NT_STATUS_NO_MEMORY;
      67             :         }
      68       16477 :         status = fsp_set_smb_fname(fsp, smb_fname);
      69       16477 :         TALLOC_FREE(smb_fname);
      70       16477 :         if (!NT_STATUS_IS_OK(status)) {
      71           0 :                 file_free(smb_req, fsp);
      72           0 :                 return status;
      73             :         }
      74             : 
      75       16477 :         if (smb_req->smb2req != NULL && smb_req->smb2req->was_encrypted) {
      76           4 :                 struct security_token *security_token = NULL;
      77           4 :                 uint16_t dialect = xconn->smb2.server.dialect;
      78           4 :                 uint16_t srv_smb_encrypt = DCERPC_SMB_ENCRYPTION_REQUIRED;
      79           4 :                 uint16_t cipher = xconn->smb2.server.cipher;
      80             :                 struct dom_sid smb3_sid;
      81             :                 uint32_t i;
      82             :                 bool ok;
      83             : 
      84           4 :                 session_info = copy_session_info(fsp, conn->session_info);
      85           4 :                 if (session_info == NULL) {
      86           0 :                         DBG_ERR("Failed to copy session info\n");
      87           0 :                         file_free(smb_req, fsp);
      88           0 :                         return NT_STATUS_NO_MEMORY;
      89             :                 }
      90           4 :                 security_token = session_info->security_token;
      91             : 
      92           4 :                 ok = dom_sid_parse(SID_SAMBA_SMB3, &smb3_sid);
      93           4 :                 if (!ok) {
      94           0 :                         file_free(smb_req, fsp);
      95           0 :                         return NT_STATUS_BUFFER_TOO_SMALL;
      96             :                 }
      97             : 
      98             :                 /*
      99             :                  * Security check:
     100             :                  *
     101             :                  * Make sure we don't have a SMB3 SID in the security token!
     102             :                  */
     103          58 :                 for (i = 0; i < security_token->num_sids; i++) {
     104             :                         int cmp;
     105             : 
     106          54 :                         cmp = dom_sid_compare_domain(&security_token->sids[i],
     107             :                                                      &smb3_sid);
     108          54 :                         if (cmp == 0) {
     109           0 :                                 DBG_ERR("ERROR: An SMB3 SID has already been "
     110             :                                         "detected in the security token!\n");
     111           0 :                                 file_free(smb_req, fsp);
     112           0 :                                 return NT_STATUS_ACCESS_DENIED;
     113             :                         }
     114             :                 }
     115             : 
     116           4 :                 ok = sid_append_rid(&smb3_sid, dialect);
     117           4 :                 ok &= sid_append_rid(&smb3_sid, srv_smb_encrypt);
     118           4 :                 ok &= sid_append_rid(&smb3_sid, cipher);
     119             : 
     120           4 :                 if (!ok) {
     121           0 :                         DBG_ERR("sid too small\n");
     122           0 :                         file_free(smb_req, fsp);
     123           0 :                         return NT_STATUS_BUFFER_TOO_SMALL;
     124             :                 }
     125             : 
     126           4 :                 status = add_sid_to_array_unique(security_token,
     127             :                                                  &smb3_sid,
     128             :                                                  &security_token->sids,
     129             :                                                  &security_token->num_sids);
     130           4 :                 if (!NT_STATUS_IS_OK(status)) {
     131           0 :                         DBG_ERR("Failed to add SMB3 SID to security token\n");
     132           0 :                         file_free(smb_req, fsp);
     133           0 :                         return status;
     134             :                 }
     135             : 
     136           4 :                 fsp->fsp_flags.encryption_required = true;
     137             :         }
     138             : 
     139       96358 :         status = np_open(fsp, name,
     140       15851 :                          conn->sconn->remote_address,
     141       15851 :                          conn->sconn->local_address,
     142             :                          session_info,
     143       15851 :                          conn->sconn->ev_ctx,
     144       15851 :                          conn->sconn->msg_ctx,
     145       16477 :                          conn->sconn->dce_ctx,
     146       16477 :                          &fsp->fake_file_handle);
     147       16477 :         if (!NT_STATUS_IS_OK(status)) {
     148          59 :                 DEBUG(10, ("np_open(%s) returned %s\n", name,
     149             :                            nt_errstr(status)));
     150          59 :                 file_free(smb_req, fsp);
     151          59 :                 return status;
     152             :         }
     153             : 
     154       16418 :         *pfsp = fsp;
     155             : 
     156       16418 :         return NT_STATUS_OK;
     157             : }
     158             : 
     159             : /****************************************************************************
     160             :  Reply to an open and X on a named pipe.
     161             :  This code is basically stolen from reply_open_and_X with some
     162             :  wrinkles to handle pipes.
     163             : ****************************************************************************/
     164             : 
     165          40 : void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req)
     166             : {
     167          40 :         const char *fname = NULL;
     168          40 :         char *pipe_name = NULL;
     169             :         files_struct *fsp;
     170          40 :         TALLOC_CTX *ctx = talloc_tos();
     171             :         NTSTATUS status;
     172             : 
     173             :         /* XXXX we need to handle passed times, sattr and flags */
     174          40 :         srvstr_pull_req_talloc(ctx, req, &pipe_name, req->buf, STR_TERMINATE);
     175          40 :         if (!pipe_name) {
     176           0 :                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
     177             :                                 ERRDOS, ERRbadpipe);
     178           0 :                 return;
     179             :         }
     180             : 
     181             :         /* If the name doesn't start \PIPE\ then this is directed */
     182             :         /* at a mailslot or something we really, really don't understand, */
     183             :         /* not just something we really don't understand. */
     184             : 
     185             : #define PIPE            "PIPE\\"
     186             : #define PIPELEN         strlen(PIPE)
     187             : 
     188          40 :         fname = pipe_name;
     189         136 :         while (fname[0] == '\\') {
     190          56 :                 fname++;
     191             :         }
     192          40 :         if (!strnequal(fname, PIPE, PIPELEN)) {
     193          16 :                 reply_nterror(req, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
     194          16 :                 return;
     195             :         }
     196          24 :         fname += PIPELEN;
     197          64 :         while (fname[0] == '\\') {
     198          16 :                 fname++;
     199             :         }
     200             : 
     201          24 :         DEBUG(4,("Opening pipe %s => %s.\n", pipe_name, fname));
     202             : 
     203             : #if 0
     204             :         /*
     205             :          * Hack for NT printers... JRA.
     206             :          */
     207             :         if(should_fail_next_srvsvc_open(fname)) {
     208             :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
     209             :                 return;
     210             :         }
     211             : #endif
     212             : 
     213          24 :         status = open_np_file(req, fname, &fsp);
     214          24 :         if (!NT_STATUS_IS_OK(status)) {
     215           8 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
     216           8 :                         reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
     217             :                                         ERRDOS, ERRbadpipe);
     218           8 :                         return;
     219             :                 }
     220           0 :                 reply_nterror(req, status);
     221           0 :                 return;
     222             :         }
     223             : 
     224             :         /* Prepare the reply */
     225          16 :         reply_outbuf(req, 15, 0);
     226             : 
     227          16 :         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
     228          16 :         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
     229             : 
     230             :         /* Mark the opened file as an existing named pipe in message mode. */
     231          16 :         SSVAL(req->outbuf,smb_vwv9,2);
     232          16 :         SSVAL(req->outbuf,smb_vwv10,0xc700);
     233             : 
     234          16 :         SSVAL(req->outbuf, smb_vwv2, fsp->fnum);
     235          16 :         SSVAL(req->outbuf, smb_vwv3, 0);     /* fmode */
     236          16 :         srv_put_dos_date3((char *)req->outbuf, smb_vwv4, 0); /* mtime */
     237          16 :         SIVAL(req->outbuf, smb_vwv6, 0);     /* size */
     238          16 :         SSVAL(req->outbuf, smb_vwv8, 0);     /* rmode */
     239          16 :         SSVAL(req->outbuf, smb_vwv11, 0x0001);
     240             : }
     241             : 
     242             : /****************************************************************************
     243             :  Reply to a write on a pipe.
     244             : ****************************************************************************/
     245             : 
     246             : struct pipe_write_state {
     247             :         size_t numtowrite;
     248             : };
     249             : 
     250             : static void pipe_write_done(struct tevent_req *subreq);
     251             : 
     252           0 : void reply_pipe_write(struct smb_request *req)
     253             : {
     254           0 :         files_struct *fsp = file_fsp(req, SVAL(req->vwv+0, 0));
     255             :         const uint8_t *data;
     256             :         struct pipe_write_state *state;
     257             :         struct tevent_req *subreq;
     258             : 
     259           0 :         if (!fsp_is_np(fsp)) {
     260           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
     261           0 :                 return;
     262             :         }
     263             : 
     264           0 :         if (fsp->vuid != req->vuid) {
     265           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
     266           0 :                 return;
     267             :         }
     268             : 
     269           0 :         state = talloc(req, struct pipe_write_state);
     270           0 :         if (state == NULL) {
     271           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
     272           0 :                 return;
     273             :         }
     274           0 :         req->async_priv = state;
     275             : 
     276           0 :         state->numtowrite = SVAL(req->vwv+1, 0);
     277             : 
     278           0 :         data = req->buf + 3;
     279             : 
     280           0 :         DEBUG(6, ("reply_pipe_write: %s, name: %s len: %d\n", fsp_fnum_dbg(fsp),
     281             :                   fsp_str_dbg(fsp), (int)state->numtowrite));
     282             : 
     283           0 :         subreq = np_write_send(state, req->sconn->ev_ctx,
     284             :                                fsp->fake_file_handle, data, state->numtowrite);
     285           0 :         if (subreq == NULL) {
     286           0 :                 TALLOC_FREE(state);
     287           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
     288           0 :                 return;
     289             :         }
     290           0 :         tevent_req_set_callback(subreq, pipe_write_done,
     291           0 :                                 talloc_move(req->conn, &req));
     292             : }
     293             : 
     294           0 : static void pipe_write_done(struct tevent_req *subreq)
     295             : {
     296           0 :         struct smb_request *req = tevent_req_callback_data(
     297             :                 subreq, struct smb_request);
     298           0 :         struct pipe_write_state *state = talloc_get_type_abort(
     299             :                 req->async_priv, struct pipe_write_state);
     300             :         NTSTATUS status;
     301           0 :         ssize_t nwritten = -1;
     302             : 
     303           0 :         status = np_write_recv(subreq, &nwritten);
     304           0 :         TALLOC_FREE(subreq);
     305           0 :         if (nwritten < 0) {
     306           0 :                 reply_nterror(req, status);
     307           0 :                 goto send;
     308             :         }
     309             : 
     310             :         /* Looks bogus to me now. Needs to be removed ? JRA. */
     311           0 :         if ((nwritten == 0 && state->numtowrite != 0)) {
     312           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
     313           0 :                 goto send;
     314             :         }
     315             : 
     316           0 :         reply_outbuf(req, 1, 0);
     317             : 
     318           0 :         SSVAL(req->outbuf,smb_vwv0,nwritten);
     319             : 
     320           0 :         DEBUG(3,("write-IPC nwritten=%d\n", (int)nwritten));
     321             : 
     322           0 :  send:
     323           0 :         if (!srv_send_smb(req->xconn, (char *)req->outbuf,
     324           0 :                           true, req->seqnum+1,
     325           0 :                           IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
     326             :                           &req->pcd)) {
     327           0 :                 exit_server_cleanly("construct_reply: srv_send_smb failed.");
     328             :         }
     329           0 :         TALLOC_FREE(req);
     330           0 : }
     331             : 
     332             : /****************************************************************************
     333             :  Reply to a write and X.
     334             : 
     335             :  This code is basically stolen from reply_write_and_X with some
     336             :  wrinkles to handle pipes.
     337             : ****************************************************************************/
     338             : 
     339             : struct pipe_write_andx_state {
     340             :         bool pipe_start_message_raw;
     341             :         size_t numtowrite;
     342             : };
     343             : 
     344             : static void pipe_write_andx_done(struct tevent_req *subreq);
     345             : 
     346           8 : void reply_pipe_write_and_X(struct smb_request *req)
     347             : {
     348           8 :         files_struct *fsp = file_fsp(req, SVAL(req->vwv+2, 0));
     349           8 :         int smb_doff = SVAL(req->vwv+11, 0);
     350             :         const uint8_t *data;
     351             :         struct pipe_write_andx_state *state;
     352             :         struct tevent_req *subreq;
     353             : 
     354           8 :         if (!fsp_is_np(fsp)) {
     355           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
     356           0 :                 return;
     357             :         }
     358             : 
     359           8 :         if (fsp->vuid != req->vuid) {
     360           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
     361           0 :                 return;
     362             :         }
     363             : 
     364           8 :         state = talloc(req, struct pipe_write_andx_state);
     365           8 :         if (state == NULL) {
     366           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
     367           0 :                 return;
     368             :         }
     369           8 :         req->async_priv = state;
     370             : 
     371           8 :         state->numtowrite = SVAL(req->vwv+10, 0);
     372           8 :         state->pipe_start_message_raw =
     373           8 :                 ((SVAL(req->vwv+7, 0) & (PIPE_START_MESSAGE|PIPE_RAW_MODE))
     374           8 :                  == (PIPE_START_MESSAGE|PIPE_RAW_MODE));
     375             : 
     376           8 :         DEBUG(6, ("reply_pipe_write_and_X: %s, name: %s len: %d\n",
     377             :                   fsp_fnum_dbg(fsp), fsp_str_dbg(fsp), (int)state->numtowrite));
     378             : 
     379           8 :         data = (const uint8_t *)smb_base(req->inbuf) + smb_doff;
     380             : 
     381           8 :         if (state->pipe_start_message_raw) {
     382             :                 /*
     383             :                  * For the start of a message in named pipe byte mode,
     384             :                  * the first two bytes are a length-of-pdu field. Ignore
     385             :                  * them (we don't trust the client). JRA.
     386             :                  */
     387           0 :                 if (state->numtowrite < 2) {
     388           0 :                         DEBUG(0,("reply_pipe_write_and_X: start of message "
     389             :                                  "set and not enough data sent.(%u)\n",
     390             :                                  (unsigned int)state->numtowrite ));
     391           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     392           0 :                         return;
     393             :                 }
     394             : 
     395           0 :                 data += 2;
     396           0 :                 state->numtowrite -= 2;
     397             :         }
     398             : 
     399           8 :         subreq = np_write_send(state, req->sconn->ev_ctx,
     400             :                                fsp->fake_file_handle, data, state->numtowrite);
     401           8 :         if (subreq == NULL) {
     402           0 :                 TALLOC_FREE(state);
     403           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
     404           0 :                 return;
     405             :         }
     406           8 :         tevent_req_set_callback(subreq, pipe_write_andx_done,
     407           8 :                                 talloc_move(req->conn, &req));
     408             : }
     409             : 
     410           8 : static void pipe_write_andx_done(struct tevent_req *subreq)
     411             : {
     412           8 :         struct smb_request *req = tevent_req_callback_data(
     413             :                 subreq, struct smb_request);
     414           8 :         struct pipe_write_andx_state *state = talloc_get_type_abort(
     415             :                 req->async_priv, struct pipe_write_andx_state);
     416             :         NTSTATUS status;
     417           8 :         ssize_t nwritten = -1;
     418             : 
     419           8 :         status = np_write_recv(subreq, &nwritten);
     420           8 :         TALLOC_FREE(subreq);
     421             : 
     422           8 :         if (!NT_STATUS_IS_OK(status)) {
     423           0 :                 reply_nterror(req, status);
     424           0 :                 goto done;
     425             :         }
     426             : 
     427             :         /* Looks bogus to me now. Is this error message correct ? JRA. */
     428           8 :         if (nwritten != state->numtowrite) {
     429           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
     430           0 :                 goto done;
     431             :         }
     432             : 
     433           8 :         reply_outbuf(req, 6, 0);
     434             : 
     435           8 :         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
     436           8 :         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
     437             : 
     438           8 :         nwritten = (state->pipe_start_message_raw ? nwritten + 2 : nwritten);
     439           8 :         SSVAL(req->outbuf,smb_vwv2,nwritten);
     440             : 
     441           8 :         DEBUG(3,("writeX-IPC nwritten=%d\n", (int)nwritten));
     442             : 
     443           8 :  done:
     444             :         /*
     445             :          * We must free here as the ownership of req was
     446             :          * moved to the connection struct in reply_pipe_write_and_X().
     447             :          */
     448           8 :         smb_request_done(req);
     449           8 : }
     450             : 
     451             : /****************************************************************************
     452             :  Reply to a read and X.
     453             :  This code is basically stolen from reply_read_and_X with some
     454             :  wrinkles to handle pipes.
     455             : ****************************************************************************/
     456             : 
     457             : struct pipe_read_andx_state {
     458             :         uint8_t *outbuf;
     459             :         int smb_mincnt;
     460             :         int smb_maxcnt;
     461             : };
     462             : 
     463             : static void pipe_read_andx_done(struct tevent_req *subreq);
     464             : 
     465          28 : void reply_pipe_read_and_X(struct smb_request *req)
     466             : {
     467          28 :         files_struct *fsp = file_fsp(req, SVAL(req->vwv+0, 0));
     468             :         uint8_t *data;
     469             :         struct pipe_read_andx_state *state;
     470             :         struct tevent_req *subreq;
     471             : 
     472             :         /* we don't use the offset given to use for pipe reads. This
     473             :            is deliberate, instead we always return the next lump of
     474             :            data on the pipe */
     475             : #if 0
     476             :         uint32_t smb_offs = IVAL(req->vwv+3, 0);
     477             : #endif
     478             : 
     479          28 :         if (!fsp_is_np(fsp)) {
     480           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
     481           0 :                 return;
     482             :         }
     483             : 
     484          28 :         if (fsp->vuid != req->vuid) {
     485           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
     486           0 :                 return;
     487             :         }
     488             : 
     489          28 :         state = talloc(req, struct pipe_read_andx_state);
     490          28 :         if (state == NULL) {
     491           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
     492           0 :                 return;
     493             :         }
     494          28 :         req->async_priv = state;
     495             : 
     496          28 :         state->smb_maxcnt = SVAL(req->vwv+5, 0);
     497          28 :         state->smb_mincnt = SVAL(req->vwv+6, 0);
     498             : 
     499          28 :         reply_outbuf(req, 12, state->smb_maxcnt + 1 /* padding byte */);
     500          28 :         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
     501          28 :         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
     502          28 :         SCVAL(smb_buf(req->outbuf), 0, 0); /* padding byte */
     503             : 
     504          28 :         data = (uint8_t *)smb_buf(req->outbuf) + 1 /* padding byte */;
     505             : 
     506             :         /*
     507             :          * We have to tell the upper layers that we're async.
     508             :          */
     509          28 :         state->outbuf = req->outbuf;
     510          28 :         req->outbuf = NULL;
     511             : 
     512          28 :         subreq = np_read_send(state, req->sconn->ev_ctx,
     513             :                               fsp->fake_file_handle, data,
     514          28 :                               state->smb_maxcnt);
     515          28 :         if (subreq == NULL) {
     516           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
     517           0 :                 return;
     518             :         }
     519          28 :         tevent_req_set_callback(subreq, pipe_read_andx_done,
     520          28 :                                 talloc_move(req->conn, &req));
     521             : }
     522             : 
     523          28 : static void pipe_read_andx_done(struct tevent_req *subreq)
     524             : {
     525          28 :         struct smb_request *req = tevent_req_callback_data(
     526             :                 subreq, struct smb_request);
     527          28 :         struct pipe_read_andx_state *state = talloc_get_type_abort(
     528             :                 req->async_priv, struct pipe_read_andx_state);
     529             :         NTSTATUS status;
     530             :         ssize_t nread;
     531             :         bool is_data_outstanding;
     532             : 
     533          28 :         status = np_read_recv(subreq, &nread, &is_data_outstanding);
     534          28 :         TALLOC_FREE(subreq);
     535          28 :         if (!NT_STATUS_IS_OK(status)) {
     536           0 :                 NTSTATUS old = status;
     537           0 :                 status = nt_status_np_pipe(old);
     538           0 :                 reply_nterror(req, status);
     539           0 :                 goto done;
     540             :         }
     541             : 
     542          28 :         req->outbuf = state->outbuf;
     543          28 :         state->outbuf = NULL;
     544             : 
     545          28 :         srv_set_message((char *)req->outbuf, 12, nread + 1 /* padding byte */,
     546             :                         false);
     547             : 
     548             : #if 0
     549             :         /*
     550             :          * we should return STATUS_BUFFER_OVERFLOW if there's
     551             :          * out standing data.
     552             :          *
     553             :          * But we can't enable it yet, as it has bad interactions
     554             :          * with fixup_chain_error_packet() in chain_reply().
     555             :          */
     556             :         if (is_data_outstanding) {
     557             :                 error_packet_set((char *)req->outbuf, ERRDOS, ERRmoredata,
     558             :                                  STATUS_BUFFER_OVERFLOW, __LINE__, __FILE__);
     559             :         }
     560             : #endif
     561             : 
     562          28 :         SSVAL(req->outbuf,smb_vwv5,nread);
     563          28 :         SSVAL(req->outbuf,smb_vwv6,
     564             :               (smb_wct - 4)     /* offset from smb header to wct */
     565             :               + 1               /* the wct field */
     566             :               + 12 * sizeof(uint16_t) /* vwv */
     567             :               + 2               /* the buflen field */
     568             :               + 1);             /* padding byte */
     569             : 
     570          28 :         DEBUG(3,("readX-IPC min=%d max=%d nread=%d\n",
     571             :                  state->smb_mincnt, state->smb_maxcnt, (int)nread));
     572             : 
     573          28 :  done:
     574             :         /*
     575             :          * We must free here as the ownership of req was
     576             :          * moved to the connection struct in reply_pipe_read_and_X().
     577             :          */
     578          28 :         smb_request_done(req);
     579          28 : }

Generated by: LCOV version 1.13