LCOV - code coverage report
Current view: top level - source3/smbd - smb1_ipc.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 123 440 28.0 %
Date: 2024-06-13 04:01:37 Functions: 5 13 38.5 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    Inter-process communication and named pipe handling
       4             :    Copyright (C) Andrew Tridgell 1992-1998
       5             : 
       6             :    SMB Version handling
       7             :    Copyright (C) John H Terpstra 1995-1998
       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 the named pipe and mailslot calls
      24             :    in the SMBtrans protocol
      25             :    */
      26             : 
      27             : #include "includes.h"
      28             : #include "smbd/smbd.h"
      29             : #include "smbd/globals.h"
      30             : #include "smbprofile.h"
      31             : #include "rpc_server/srv_pipe_hnd.h"
      32             : #include "source3/lib/substitute.h"
      33             : 
      34             : #define NERR_notsupported 50
      35             : 
      36             : static void api_no_reply(connection_struct *conn, struct smb_request *req);
      37             : 
      38             : /*******************************************************************
      39             :  copies parameters and data, as needed, into the smb buffer
      40             : 
      41             :  *both* the data and params sections should be aligned.  this
      42             :  is fudged in the rpc pipes by 
      43             :  at present, only the data section is.  this may be a possible
      44             :  cause of some of the ipc problems being experienced.  lkcl26dec97
      45             : 
      46             :  ******************************************************************/
      47             : 
      48           4 : static void copy_trans_params_and_data(char *outbuf, int align,
      49             :                                 char *rparam, int param_offset, int param_len,
      50             :                                 char *rdata, int data_offset, int data_len)
      51             : {
      52           4 :         char *copy_into = smb_buf(outbuf);
      53             : 
      54           4 :         if(param_len < 0)
      55           0 :                 param_len = 0;
      56             : 
      57           4 :         if(data_len < 0)
      58           0 :                 data_len = 0;
      59             : 
      60           4 :         DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d] (align %d)\n",
      61             :                         param_offset, param_offset + param_len,
      62             :                         data_offset , data_offset  + data_len,
      63             :                         align));
      64             : 
      65           4 :         *copy_into = '\0';
      66             : 
      67           4 :         copy_into += 1;
      68             : 
      69           4 :         if (param_len)
      70           4 :                 memcpy(copy_into, &rparam[param_offset], param_len);
      71             : 
      72           4 :         copy_into += param_len;
      73           4 :         if (align) {
      74           0 :                 memset(copy_into, '\0', align);
      75             :         }
      76             : 
      77           4 :         copy_into += align;
      78             : 
      79           4 :         if (data_len )
      80           4 :                 memcpy(copy_into, &rdata[data_offset], data_len);
      81           4 : }
      82             : 
      83             : /****************************************************************************
      84             :  Send a trans reply.
      85             :  ****************************************************************************/
      86             : 
      87           4 : void send_trans_reply(connection_struct *conn,
      88             :                       struct smb_request *req,
      89             :                       char *rparam, int rparam_len,
      90             :                       char *rdata, int rdata_len,
      91             :                       bool buffer_too_large)
      92             : {
      93             :         int this_ldata,this_lparam;
      94           4 :         int tot_data_sent = 0;
      95           4 :         int tot_param_sent = 0;
      96             :         int align;
      97             : 
      98           4 :         int ldata  = rdata  ? rdata_len : 0;
      99           4 :         int lparam = rparam ? rparam_len : 0;
     100           4 :         struct smbXsrv_connection *xconn = req->xconn;
     101           4 :         int max_send = xconn->smb1.sessions.max_send;
     102             :         /* HACK: make sure we send at least 128 byte in one go */
     103           4 :         int hdr_overhead = SMB_BUFFER_SIZE_MIN - 128;
     104             : 
     105           4 :         if (buffer_too_large)
     106           0 :                 DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata ));
     107             : 
     108           4 :         this_lparam = MIN(lparam,max_send - hdr_overhead);
     109           4 :         this_ldata  = MIN(ldata,max_send - (hdr_overhead+this_lparam));
     110             : 
     111           4 :         align = ((this_lparam)%4);
     112             : 
     113           4 :         reply_smb1_outbuf(req, 10, 1+align+this_ldata+this_lparam);
     114             : 
     115             :         /*
     116             :          * We might have SMBtranss in req which was transferred to the outbuf,
     117             :          * fix that.
     118             :          */
     119           4 :         SCVAL(req->outbuf, smb_com, SMBtrans);
     120             : 
     121           4 :         copy_trans_params_and_data((char *)req->outbuf, align,
     122             :                                 rparam, tot_param_sent, this_lparam,
     123             :                                 rdata, tot_data_sent, this_ldata);
     124             : 
     125           4 :         SSVAL(req->outbuf,smb_vwv0,lparam);
     126           4 :         SSVAL(req->outbuf,smb_vwv1,ldata);
     127           4 :         SSVAL(req->outbuf,smb_vwv3,this_lparam);
     128           4 :         SSVAL(req->outbuf,smb_vwv4,
     129             :               smb_offset(smb_buf(req->outbuf)+1, req->outbuf));
     130           4 :         SSVAL(req->outbuf,smb_vwv5,0);
     131           4 :         SSVAL(req->outbuf,smb_vwv6,this_ldata);
     132           4 :         SSVAL(req->outbuf,smb_vwv7,
     133             :               smb_offset(smb_buf(req->outbuf)+1+this_lparam+align,
     134             :                          req->outbuf));
     135           4 :         SSVAL(req->outbuf,smb_vwv8,0);
     136           4 :         SSVAL(req->outbuf,smb_vwv9,0);
     137             : 
     138           4 :         if (buffer_too_large) {
     139           0 :                 error_packet_set((char *)req->outbuf, ERRDOS, ERRmoredata,
     140           0 :                                  STATUS_BUFFER_OVERFLOW, __LINE__, __FILE__);
     141             :         }
     142             : 
     143           4 :         show_msg((char *)req->outbuf);
     144           8 :         if (!smb1_srv_send(xconn, (char *)req->outbuf,
     145           4 :                           true, req->seqnum+1,
     146           4 :                           IS_CONN_ENCRYPTED(conn), &req->pcd)) {
     147           0 :                 exit_server_cleanly("send_trans_reply: smb1_srv_send failed.");
     148             :         }
     149             : 
     150           4 :         TALLOC_FREE(req->outbuf);
     151             : 
     152           4 :         tot_data_sent = this_ldata;
     153           4 :         tot_param_sent = this_lparam;
     154             : 
     155           6 :         while (tot_data_sent < ldata || tot_param_sent < lparam)
     156             :         {
     157           0 :                 this_lparam = MIN(lparam-tot_param_sent,
     158             :                                   max_send - hdr_overhead);
     159           0 :                 this_ldata  = MIN(ldata -tot_data_sent,
     160             :                                   max_send - (hdr_overhead+this_lparam));
     161             : 
     162           0 :                 if(this_lparam < 0)
     163           0 :                         this_lparam = 0;
     164             : 
     165           0 :                 if(this_ldata < 0)
     166           0 :                         this_ldata = 0;
     167             : 
     168           0 :                 align = (this_lparam%4);
     169             : 
     170           0 :                 reply_smb1_outbuf(req, 10, 1+align+this_ldata+this_lparam);
     171             : 
     172             :                 /*
     173             :                  * We might have SMBtranss in req which was transferred to the
     174             :                  * outbuf, fix that.
     175             :                  */
     176           0 :                 SCVAL(req->outbuf, smb_com, SMBtrans);
     177             : 
     178           0 :                 copy_trans_params_and_data((char *)req->outbuf, align,
     179             :                                            rparam, tot_param_sent, this_lparam,
     180             :                                            rdata, tot_data_sent, this_ldata);
     181             : 
     182           0 :                 SSVAL(req->outbuf,smb_vwv0,lparam);
     183           0 :                 SSVAL(req->outbuf,smb_vwv1,ldata);
     184             : 
     185           0 :                 SSVAL(req->outbuf,smb_vwv3,this_lparam);
     186           0 :                 SSVAL(req->outbuf,smb_vwv4,
     187             :                       smb_offset(smb_buf(req->outbuf)+1,req->outbuf));
     188           0 :                 SSVAL(req->outbuf,smb_vwv5,tot_param_sent);
     189           0 :                 SSVAL(req->outbuf,smb_vwv6,this_ldata);
     190           0 :                 SSVAL(req->outbuf,smb_vwv7,
     191             :                       smb_offset(smb_buf(req->outbuf)+1+this_lparam+align,
     192             :                                  req->outbuf));
     193           0 :                 SSVAL(req->outbuf,smb_vwv8,tot_data_sent);
     194           0 :                 SSVAL(req->outbuf,smb_vwv9,0);
     195             : 
     196           0 :                 if (buffer_too_large) {
     197           0 :                         error_packet_set((char *)req->outbuf,
     198             :                                          ERRDOS, ERRmoredata,
     199           0 :                                          STATUS_BUFFER_OVERFLOW,
     200             :                                          __LINE__, __FILE__);
     201             :                 }
     202             : 
     203           0 :                 show_msg((char *)req->outbuf);
     204           0 :                 if (!smb1_srv_send(xconn, (char *)req->outbuf,
     205           0 :                                   true, req->seqnum+1,
     206           0 :                                   IS_CONN_ENCRYPTED(conn), &req->pcd))
     207           0 :                         exit_server_cleanly("send_trans_reply: smb1_srv_send "
     208             :                                             "failed.");
     209             : 
     210           0 :                 tot_data_sent  += this_ldata;
     211           0 :                 tot_param_sent += this_lparam;
     212           0 :                 TALLOC_FREE(req->outbuf);
     213             :         }
     214           4 : }
     215             : 
     216             : /****************************************************************************
     217             :  Start the first part of an RPC reply which began with an SMBtrans request.
     218             : ****************************************************************************/
     219             : 
     220             : struct dcerpc_cmd_state {
     221             :         struct fake_file_handle *handle;
     222             :         uint8_t *data;
     223             :         size_t num_data;
     224             :         size_t max_read;
     225             : };
     226             : 
     227             : static void api_dcerpc_cmd_write_done(struct tevent_req *subreq);
     228             : static void api_dcerpc_cmd_read_done(struct tevent_req *subreq);
     229             : 
     230           0 : static void api_dcerpc_cmd(connection_struct *conn, struct smb_request *req,
     231             :                            files_struct *fsp, uint8_t *data, size_t length,
     232             :                            size_t max_read)
     233             : {
     234             :         struct tevent_req *subreq;
     235             :         struct dcerpc_cmd_state *state;
     236             :         bool busy;
     237             : 
     238           0 :         if (!fsp_is_np(fsp)) {
     239           0 :                 api_no_reply(conn, req);
     240           0 :                 return;
     241             :         }
     242             : 
     243             :         /*
     244             :          * Trans requests are only allowed
     245             :          * if no other Trans or Read is active
     246             :          */
     247           0 :         busy = np_read_in_progress(fsp->fake_file_handle);
     248           0 :         if (busy) {
     249           0 :                 reply_nterror(req, NT_STATUS_PIPE_BUSY);
     250           0 :                 return;
     251             :         }
     252             : 
     253           0 :         state = talloc(req, struct dcerpc_cmd_state);
     254           0 :         if (state == NULL) {
     255           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
     256           0 :                 return;
     257             :         }
     258           0 :         req->async_priv = state;
     259             : 
     260           0 :         state->handle = fsp->fake_file_handle;
     261             : 
     262             :         /*
     263             :          * This memdup severely sucks. But doing it properly essentially means
     264             :          * to rewrite lanman.c, something which I don't really want to do now.
     265             :          */
     266           0 :         state->data = (uint8_t *)talloc_memdup(state, data, length);
     267           0 :         if (state->data == NULL) {
     268           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
     269           0 :                 return;
     270             :         }
     271           0 :         state->num_data = length;
     272           0 :         state->max_read = max_read;
     273             : 
     274           0 :         subreq = np_write_send(state, req->sconn->ev_ctx, state->handle,
     275           0 :                                state->data, length);
     276           0 :         if (subreq == NULL) {
     277           0 :                 TALLOC_FREE(state);
     278           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
     279           0 :                 return;
     280             :         }
     281           0 :         tevent_req_set_callback(subreq, api_dcerpc_cmd_write_done,
     282             :                                 talloc_move(conn, &req));
     283             : }
     284             : 
     285           0 : static void api_dcerpc_cmd_write_done(struct tevent_req *subreq)
     286             : {
     287           0 :         struct smb_request *req = tevent_req_callback_data(
     288             :                 subreq, struct smb_request);
     289           0 :         struct dcerpc_cmd_state *state = talloc_get_type_abort(
     290             :                 req->async_priv, struct dcerpc_cmd_state);
     291             :         NTSTATUS status;
     292           0 :         ssize_t nwritten = -1;
     293             : 
     294           0 :         status = np_write_recv(subreq, &nwritten);
     295           0 :         TALLOC_FREE(subreq);
     296           0 :         if (!NT_STATUS_IS_OK(status)) {
     297           0 :                 NTSTATUS old = status;
     298           0 :                 status = nt_status_np_pipe(old);
     299             : 
     300           0 :                 DEBUG(10, ("Could not write to pipe: %s%s%s\n",
     301             :                            nt_errstr(old),
     302             :                            NT_STATUS_EQUAL(old, status)?"":" => ",
     303             :                            NT_STATUS_EQUAL(old, status)?"":nt_errstr(status)));
     304           0 :                 reply_nterror(req, status);
     305           0 :                 goto send;
     306             :         }
     307           0 :         if (nwritten != state->num_data) {
     308           0 :                 status = NT_STATUS_PIPE_NOT_AVAILABLE;
     309           0 :                 DEBUG(10, ("Could not write to pipe: (%d/%d) => %s\n",
     310             :                            (int)state->num_data,
     311             :                            (int)nwritten, nt_errstr(status)));
     312           0 :                 reply_nterror(req, status);
     313           0 :                 goto send;
     314             :         }
     315             : 
     316           0 :         state->data = talloc_realloc(state, state->data, uint8_t,
     317             :                                            state->max_read);
     318           0 :         if (state->data == NULL) {
     319           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
     320           0 :                 goto send;
     321             :         }
     322             : 
     323           0 :         subreq = np_read_send(state, req->sconn->ev_ctx,
     324             :                               state->handle, state->data, state->max_read);
     325           0 :         if (subreq == NULL) {
     326           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
     327           0 :                 goto send;
     328             :         }
     329           0 :         tevent_req_set_callback(subreq, api_dcerpc_cmd_read_done, req);
     330           0 :         return;
     331             : 
     332           0 :  send:
     333           0 :         if (!smb1_srv_send(
     334           0 :                     req->xconn, (char *)req->outbuf,
     335           0 :                     true, req->seqnum+1,
     336           0 :                     IS_CONN_ENCRYPTED(req->conn) || req->encrypted,
     337             :                     &req->pcd)) {
     338           0 :                 exit_server_cleanly("api_dcerpc_cmd_write_done: "
     339             :                                     "smb1_srv_send failed.");
     340             :         }
     341           0 :         TALLOC_FREE(req);
     342             : }
     343             : 
     344           0 : static void api_dcerpc_cmd_read_done(struct tevent_req *subreq)
     345             : {
     346           0 :         struct smb_request *req = tevent_req_callback_data(
     347             :                 subreq, struct smb_request);
     348           0 :         struct dcerpc_cmd_state *state = talloc_get_type_abort(
     349             :                 req->async_priv, struct dcerpc_cmd_state);
     350             :         NTSTATUS status;
     351             :         ssize_t nread;
     352             :         bool is_data_outstanding;
     353             : 
     354           0 :         status = np_read_recv(subreq, &nread, &is_data_outstanding);
     355           0 :         TALLOC_FREE(subreq);
     356             : 
     357           0 :         if (!NT_STATUS_IS_OK(status)) {
     358           0 :                 NTSTATUS old = status;
     359           0 :                 status = nt_status_np_pipe(old);
     360             : 
     361           0 :                 DEBUG(10, ("Could not read from to pipe: %s%s%s\n",
     362             :                            nt_errstr(old),
     363             :                            NT_STATUS_EQUAL(old, status)?"":" => ",
     364             :                            NT_STATUS_EQUAL(old, status)?"":nt_errstr(status)));
     365           0 :                 reply_nterror(req, status);
     366             : 
     367           0 :                 if (!smb1_srv_send(req->xconn, (char *)req->outbuf,
     368           0 :                                   true, req->seqnum+1,
     369           0 :                                   IS_CONN_ENCRYPTED(req->conn)
     370           0 :                                   ||req->encrypted, &req->pcd)) {
     371           0 :                         exit_server_cleanly("api_dcerpc_cmd_read_done: "
     372             :                                             "smb1_srv_send failed.");
     373             :                 }
     374           0 :                 TALLOC_FREE(req);
     375           0 :                 return;
     376             :         }
     377             : 
     378           0 :         send_trans_reply(req->conn, req, NULL, 0, (char *)state->data, nread,
     379             :                          is_data_outstanding);
     380           0 :         TALLOC_FREE(req);
     381             : }
     382             : 
     383             : /****************************************************************************
     384             :  WaitNamedPipeHandleState 
     385             : ****************************************************************************/
     386             : 
     387           0 : static void api_WNPHS(connection_struct *conn, struct smb_request *req,
     388             :                       struct files_struct *fsp, char *param, int param_len)
     389             : {
     390           0 :         if (!param || param_len < 2) {
     391           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     392           0 :                 return;
     393             :         }
     394             : 
     395           0 :         DEBUG(4,("WaitNamedPipeHandleState priority %x\n",
     396             :                  (int)SVAL(param,0)));
     397             : 
     398           0 :         send_trans_reply(conn, req, NULL, 0, NULL, 0, False);
     399             : }
     400             : 
     401             : 
     402             : /****************************************************************************
     403             :  SetNamedPipeHandleState 
     404             : ****************************************************************************/
     405             : 
     406           0 : static void api_SNPHS(connection_struct *conn, struct smb_request *req,
     407             :                       struct files_struct *fsp, char *param, int param_len)
     408             : {
     409           0 :         if (!param || param_len < 2) {
     410           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     411           0 :                 return;
     412             :         }
     413             : 
     414           0 :         DEBUG(4,("SetNamedPipeHandleState to code %x\n", (int)SVAL(param,0)));
     415             : 
     416           0 :         send_trans_reply(conn, req, NULL, 0, NULL, 0, False);
     417             : }
     418             : 
     419             : 
     420             : /****************************************************************************
     421             :  When no reply is generated, indicate unsupported.
     422             :  ****************************************************************************/
     423             : 
     424           0 : static void api_no_reply(connection_struct *conn, struct smb_request *req)
     425             : {
     426             :         char rparam[4];
     427             : 
     428             :         /* unsupported */
     429           0 :         SSVAL(rparam,0,NERR_notsupported);
     430           0 :         SSVAL(rparam,2,0); /* converter word */
     431             : 
     432           0 :         DEBUG(3,("Unsupported API fd command\n"));
     433             : 
     434             :         /* now send the reply */
     435           0 :         send_trans_reply(conn, req, rparam, 4, NULL, 0, False);
     436             : 
     437           0 :         return;
     438             : }
     439             : 
     440             : /****************************************************************************
     441             :  Handle remote api calls delivered to a named pipe already opened.
     442             :  ****************************************************************************/
     443             : 
     444           0 : static void api_fd_reply(connection_struct *conn, uint64_t vuid,
     445             :                          struct smb_request *req,
     446             :                          uint16_t *setup, uint8_t *data, char *params,
     447             :                          int suwcnt, int tdscnt, int tpscnt,
     448             :                          int mdrcnt, int mprcnt)
     449             : {
     450             :         struct files_struct *fsp;
     451             :         int pnum;
     452             :         int subcommand;
     453             : 
     454           0 :         DEBUG(5,("api_fd_reply\n"));
     455             : 
     456             :         /* First find out the name of this file. */
     457           0 :         if (suwcnt != 2) {
     458           0 :                 DEBUG(0,("Unexpected named pipe transaction.\n"));
     459           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     460           0 :                 return;
     461             :         }
     462             : 
     463             :         /* Get the file handle and hence the file name. */
     464             :         /* 
     465             :          * NB. The setup array has already been transformed
     466             :          * via SVAL and so is in host byte order.
     467             :          */
     468           0 :         pnum = ((int)setup[1]) & 0xFFFF;
     469           0 :         subcommand = ((int)setup[0]) & 0xFFFF;
     470             : 
     471           0 :         fsp = file_fsp(req, pnum);
     472             : 
     473           0 :         if (!fsp_is_np(fsp)) {
     474           0 :                 if (subcommand == TRANSACT_WAITNAMEDPIPEHANDLESTATE) {
     475             :                         /* Win9x does this call with a unicode pipe name, not a pnum. */
     476             :                         /* Just return success for now... */
     477           0 :                         DEBUG(3,("Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name\n"));
     478           0 :                         send_trans_reply(conn, req, NULL, 0, NULL, 0, False);
     479           0 :                         return;
     480             :                 }
     481             : 
     482           0 :                 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
     483           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
     484           0 :                 return;
     485             :         }
     486             : 
     487           0 :         if (vuid != fsp->vuid) {
     488           0 :                 DEBUG(1, ("Got pipe request (pnum %x) using invalid VUID %llu, "
     489             :                           "expected %llu\n", pnum, (unsigned long long)vuid,
     490             :                           (unsigned long long)fsp->vuid));
     491           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
     492           0 :                 return;
     493             :         }
     494             : 
     495           0 :         DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)\n",
     496             :                  subcommand, fsp_str_dbg(fsp), pnum));
     497             : 
     498           0 :         DEBUG(10, ("api_fd_reply: p:%p max_trans_reply: %d\n", fsp, mdrcnt));
     499             : 
     500           0 :         switch (subcommand) {
     501           0 :         case TRANSACT_DCERPCCMD: {
     502             :                 /* dce/rpc command */
     503           0 :                 api_dcerpc_cmd(conn, req, fsp, (uint8_t *)data, tdscnt,
     504             :                                mdrcnt);
     505           0 :                 break;
     506             :         }
     507           0 :         case TRANSACT_WAITNAMEDPIPEHANDLESTATE:
     508             :                 /* Wait Named Pipe Handle state */
     509           0 :                 api_WNPHS(conn, req, fsp, params, tpscnt);
     510           0 :                 break;
     511           0 :         case TRANSACT_SETNAMEDPIPEHANDLESTATE:
     512             :                 /* Set Named Pipe Handle state */
     513           0 :                 api_SNPHS(conn, req, fsp, params, tpscnt);
     514           0 :                 break;
     515           0 :         default:
     516           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     517           0 :                 return;
     518             :         }
     519             : }
     520             : 
     521             : /****************************************************************************
     522             :  Handle named pipe commands.
     523             : ****************************************************************************/
     524             : 
     525           4 : static void named_pipe(connection_struct *conn, uint64_t vuid,
     526             :                        struct smb_request *req,
     527             :                        const char *name, uint16_t *setup,
     528             :                        char *data, char *params,
     529             :                        int suwcnt, int tdscnt,int tpscnt,
     530             :                        int msrcnt, int mdrcnt, int mprcnt)
     531             : {
     532           4 :         DEBUG(3,("named pipe command on <%s> name\n", name));
     533             : 
     534           4 :         if (strequal(name,"LANMAN")) {
     535           4 :                 api_reply(conn, vuid, req,
     536             :                           data, params,
     537             :                           tdscnt, tpscnt,
     538             :                           mdrcnt, mprcnt);
     539           4 :                 return;
     540             :         }
     541             : 
     542           0 :         if (strequal(name,"WKSSVC") ||
     543           0 :             strequal(name,"SRVSVC") ||
     544           0 :             strequal(name,"WINREG") ||
     545           0 :             strequal(name,"SAMR") ||
     546           0 :             strequal(name,"LSARPC")) {
     547             : 
     548           0 :                 DEBUG(4,("named pipe command from Win95 (wow!)\n"));
     549             : 
     550           0 :                 api_fd_reply(conn, vuid, req,
     551             :                              setup, (uint8_t *)data, params,
     552             :                              suwcnt, tdscnt, tpscnt,
     553             :                              mdrcnt, mprcnt);
     554           0 :                 return;
     555             :         }
     556             : 
     557           0 :         if (strlen(name) < 1) {
     558           0 :                 api_fd_reply(conn, vuid, req,
     559             :                              setup, (uint8_t *)data,
     560             :                              params, suwcnt, tdscnt,
     561             :                              tpscnt, mdrcnt, mprcnt);
     562           0 :                 return;
     563             :         }
     564             : 
     565           0 :         if (setup)
     566           0 :                 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n",
     567             :                          (int)setup[0],(int)setup[1]));
     568             : 
     569           0 :         reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
     570           0 :         return;
     571             : }
     572             : 
     573           4 : static void handle_trans(connection_struct *conn, struct smb_request *req,
     574             :                          struct trans_state *state)
     575             : {
     576             :         char *local_machine_name;
     577           4 :         int name_offset = 0;
     578             : 
     579           4 :         DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n",
     580             :                  state->name,(unsigned int)state->total_data,(unsigned int)state->total_param,
     581             :                  (unsigned int)state->setup_count));
     582             : 
     583             :         /*
     584             :          * WinCE wierdness....
     585             :          */
     586             : 
     587           4 :         local_machine_name = talloc_asprintf(state, "\\%s\\",
     588             :                                              get_local_machine_name());
     589             : 
     590           4 :         if (local_machine_name == NULL) {
     591           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
     592           0 :                 return;
     593             :         }
     594             : 
     595           4 :         if (strnequal(state->name, local_machine_name,
     596             :                       strlen(local_machine_name))) {
     597           0 :                 name_offset = strlen(local_machine_name)-1;
     598             :         }
     599             : 
     600           4 :         if (!strnequal(&state->name[name_offset], "\\PIPE",
     601             :                        strlen("\\PIPE"))) {
     602           0 :                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
     603           0 :                 return;
     604             :         }
     605             : 
     606           4 :         name_offset += strlen("\\PIPE");
     607             : 
     608             :         /* Win9x weirdness.  When talking to a unicode server Win9x
     609             :            only sends \PIPE instead of \PIPE\ */
     610             : 
     611           4 :         if (state->name[name_offset] == '\\')
     612           4 :                 name_offset++;
     613             : 
     614           4 :         DEBUG(5,("calling named_pipe\n"));
     615          18 :         named_pipe(conn, state->vuid, req,
     616           6 :                    state->name+name_offset,
     617             :                    state->setup,state->data,
     618             :                    state->param,
     619           6 :                    state->setup_count,state->total_data,
     620           4 :                    state->total_param,
     621           4 :                    state->max_setup_return,
     622           4 :                    state->max_data_return,
     623           4 :                    state->max_param_return);
     624             : 
     625           4 :         if (state->close_on_completion) {
     626             :                 struct smbXsrv_tcon *tcon;
     627             :                 NTSTATUS status;
     628             : 
     629           0 :                 tcon = conn->tcon;
     630           0 :                 req->conn = NULL;
     631           0 :                 conn = NULL;
     632             : 
     633             :                 /*
     634             :                  * TODO: cancel all outstanding requests on the tcon
     635             :                  */
     636           0 :                 status = smbXsrv_tcon_disconnect(tcon, state->vuid);
     637           0 :                 if (!NT_STATUS_IS_OK(status)) {
     638           0 :                         DEBUG(0, ("handle_trans: "
     639             :                                   "smbXsrv_tcon_disconnect() failed: %s\n",
     640             :                                   nt_errstr(status)));
     641             :                         /*
     642             :                          * If we hit this case, there is something completely
     643             :                          * wrong, so we better disconnect the transport connection.
     644             :                          */
     645           0 :                         exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
     646             :                         return;
     647             :                 }
     648             : 
     649           0 :                 TALLOC_FREE(tcon);
     650             :         }
     651             : 
     652           4 :         return;
     653             : }
     654             : 
     655             : /****************************************************************************
     656             :  Reply to a SMBtrans.
     657             :  ****************************************************************************/
     658             : 
     659           4 : void reply_trans(struct smb_request *req)
     660             : {
     661           4 :         connection_struct *conn = req->conn;
     662             :         unsigned int dsoff;
     663             :         unsigned int dscnt;
     664             :         unsigned int psoff;
     665             :         unsigned int pscnt;
     666             :         struct trans_state *state;
     667             :         NTSTATUS result;
     668             : 
     669           4 :         START_PROFILE(SMBtrans);
     670             : 
     671           4 :         if (req->wct < 14) {
     672           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     673           0 :                 END_PROFILE(SMBtrans);
     674           0 :                 return;
     675             :         }
     676             : 
     677           4 :         dsoff = SVAL(req->vwv+12, 0);
     678           4 :         dscnt = SVAL(req->vwv+11, 0);
     679           4 :         psoff = SVAL(req->vwv+10, 0);
     680           4 :         pscnt = SVAL(req->vwv+9, 0);
     681             : 
     682           4 :         result = allow_new_trans(conn->pending_trans, req->mid);
     683           4 :         if (!NT_STATUS_IS_OK(result)) {
     684           0 :                 DEBUG(2, ("Got invalid trans request: %s\n",
     685             :                           nt_errstr(result)));
     686           0 :                 reply_nterror(req, result);
     687           0 :                 END_PROFILE(SMBtrans);
     688           0 :                 return;
     689             :         }
     690             : 
     691           4 :         if ((state = talloc_zero(conn, struct trans_state)) == NULL) {
     692           0 :                 DEBUG(0, ("talloc failed\n"));
     693           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
     694           0 :                 END_PROFILE(SMBtrans);
     695           0 :                 return;
     696             :         }
     697             : 
     698           4 :         state->cmd = SMBtrans;
     699             : 
     700           4 :         state->mid = req->mid;
     701           4 :         state->vuid = req->vuid;
     702           4 :         state->setup_count = CVAL(req->vwv+13, 0);
     703           4 :         state->setup = NULL;
     704           4 :         state->total_param = SVAL(req->vwv+0, 0);
     705           4 :         state->param = NULL;
     706           4 :         state->total_data = SVAL(req->vwv+1, 0);
     707           4 :         state->data = NULL;
     708           4 :         state->max_param_return = SVAL(req->vwv+2, 0);
     709           4 :         state->max_data_return = SVAL(req->vwv+3, 0);
     710           4 :         state->max_setup_return = CVAL(req->vwv+4, 0);
     711           4 :         state->close_on_completion = BITSETW(req->vwv+5, 0);
     712           4 :         state->one_way = BITSETW(req->vwv+5, 1);
     713             : 
     714           4 :         srvstr_pull_req_talloc(state, req, &state->name, req->buf,
     715             :                                STR_TERMINATE);
     716             : 
     717           6 :         if ((dscnt > state->total_data) || (pscnt > state->total_param) ||
     718           4 :                         !state->name)
     719           0 :                 goto bad_param;
     720             : 
     721           4 :         if (state->total_data)  {
     722             : 
     723           0 :                 if (smb_buffer_oob(state->total_data, 0, dscnt)
     724           0 :                     || smb_buffer_oob(smb_len(req->inbuf), dsoff, dscnt)) {
     725           0 :                         goto bad_param;
     726             :                 }
     727             : 
     728             :                 /* Can't use talloc here, the core routines do realloc on the
     729             :                  * params and data. Out of paranoia, 100 bytes too many. */
     730           0 :                 state->data = (char *)SMB_MALLOC(state->total_data+100);
     731           0 :                 if (state->data == NULL) {
     732           0 :                         DEBUG(0,("reply_trans: data malloc fail for %u "
     733             :                                  "bytes !\n", (unsigned int)state->total_data));
     734           0 :                         TALLOC_FREE(state);
     735           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
     736           0 :                         END_PROFILE(SMBtrans);
     737           0 :                         return;
     738             :                 }
     739             :                 /* null-terminate the slack space */
     740           0 :                 memset(&state->data[state->total_data], 0, 100);
     741             : 
     742           0 :                 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
     743             :         }
     744             : 
     745           4 :         if (state->total_param) {
     746             : 
     747           4 :                 if (smb_buffer_oob(state->total_param, 0, pscnt)
     748           4 :                     || smb_buffer_oob(smb_len(req->inbuf), psoff, pscnt)) {
     749           0 :                         goto bad_param;
     750             :                 }
     751             : 
     752             :                 /* Can't use talloc here, the core routines do realloc on the
     753             :                  * params and data. Out of paranoia, 100 bytes too many */
     754           4 :                 state->param = (char *)SMB_MALLOC(state->total_param+100);
     755           4 :                 if (state->param == NULL) {
     756           0 :                         DEBUG(0,("reply_trans: param malloc fail for %u "
     757             :                                  "bytes !\n", (unsigned int)state->total_param));
     758           0 :                         SAFE_FREE(state->data);
     759           0 :                         TALLOC_FREE(state);
     760           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
     761           0 :                         END_PROFILE(SMBtrans);
     762           0 :                         return;
     763             :                 } 
     764             :                 /* null-terminate the slack space */
     765           4 :                 memset(&state->param[state->total_param], 0, 100);
     766             : 
     767           4 :                 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
     768             :         }
     769             : 
     770           4 :         state->received_data  = dscnt;
     771           4 :         state->received_param = pscnt;
     772             : 
     773           4 :         if (state->setup_count) {
     774             :                 unsigned int i;
     775             : 
     776             :                 /*
     777             :                  * No overflow possible here, state->setup_count is an
     778             :                  * unsigned int, being filled by a single byte from
     779             :                  * CVAL(req->vwv+13, 0) above. The cast in the comparison
     780             :                  * below is not necessary, it's here to clarify things. The
     781             :                  * validity of req->vwv and req->wct has been checked in
     782             :                  * init_smb1_request already.
     783             :                  */
     784           0 :                 if (state->setup_count + 14 > (unsigned int)req->wct) {
     785           0 :                         goto bad_param;
     786             :                 }
     787             : 
     788           0 :                 if((state->setup = talloc_array(
     789             :                             state, uint16_t, state->setup_count)) == NULL) {
     790           0 :                         DEBUG(0,("reply_trans: setup malloc fail for %u "
     791             :                                  "bytes !\n", (unsigned int)
     792             :                                  (state->setup_count * sizeof(uint16_t))));
     793           0 :                         SAFE_FREE(state->data);
     794           0 :                         SAFE_FREE(state->param);
     795           0 :                         TALLOC_FREE(state);
     796           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
     797           0 :                         END_PROFILE(SMBtrans);
     798           0 :                         return;
     799             :                 } 
     800             : 
     801           0 :                 for (i=0;i<state->setup_count;i++) {
     802           0 :                         state->setup[i] = SVAL(req->vwv + 14 + i, 0);
     803             :                 }
     804             :         }
     805             : 
     806           4 :         state->received_param = pscnt;
     807             : 
     808           6 :         if ((state->received_param != state->total_param) ||
     809           4 :             (state->received_data != state->total_data)) {
     810           0 :                 DLIST_ADD(conn->pending_trans, state);
     811             : 
     812             :                 /* We need to send an interim response then receive the rest
     813             :                    of the parameter/data bytes */
     814           0 :                 reply_smb1_outbuf(req, 0, 0);
     815           0 :                 show_msg((char *)req->outbuf);
     816           0 :                 END_PROFILE(SMBtrans);
     817           0 :                 return;
     818             :         }
     819             : 
     820           4 :         talloc_steal(talloc_tos(), state);
     821             : 
     822           4 :         handle_trans(conn, req, state);
     823             : 
     824           4 :         SAFE_FREE(state->data);
     825           4 :         SAFE_FREE(state->param);
     826           4 :         TALLOC_FREE(state);
     827             : 
     828           4 :         END_PROFILE(SMBtrans);
     829           4 :         return;
     830             : 
     831           0 :   bad_param:
     832             : 
     833           0 :         DEBUG(0,("reply_trans: invalid trans parameters\n"));
     834           0 :         SAFE_FREE(state->data);
     835           0 :         SAFE_FREE(state->param);
     836           0 :         TALLOC_FREE(state);
     837           0 :         END_PROFILE(SMBtrans);
     838           0 :         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     839           0 :         return;
     840             : }
     841             : 
     842             : /****************************************************************************
     843             :  Reply to a secondary SMBtrans.
     844             :  ****************************************************************************/
     845             : 
     846           0 : void reply_transs(struct smb_request *req)
     847             : {
     848           0 :         connection_struct *conn = req->conn;
     849             :         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
     850             :         struct trans_state *state;
     851             : 
     852           0 :         START_PROFILE(SMBtranss);
     853             : 
     854           0 :         show_msg((const char *)req->inbuf);
     855             : 
     856           0 :         if (req->wct < 8) {
     857           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     858           0 :                 END_PROFILE(SMBtranss);
     859           0 :                 return;
     860             :         }
     861             : 
     862           0 :         for (state = conn->pending_trans; state != NULL;
     863           0 :              state = state->next) {
     864           0 :                 if (state->mid == req->mid) {
     865           0 :                         break;
     866             :                 }
     867             :         }
     868             : 
     869           0 :         if ((state == NULL) || (state->cmd != SMBtrans)) {
     870           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     871           0 :                 END_PROFILE(SMBtranss);
     872           0 :                 return;
     873             :         }
     874             : 
     875             :         /* Revise total_params and total_data in case they have changed
     876             :          * downwards */
     877             : 
     878           0 :         if (SVAL(req->vwv+0, 0) < state->total_param)
     879           0 :                 state->total_param = SVAL(req->vwv+0, 0);
     880           0 :         if (SVAL(req->vwv+1, 0) < state->total_data)
     881           0 :                 state->total_data = SVAL(req->vwv+1, 0);
     882             : 
     883           0 :         pcnt = SVAL(req->vwv+2, 0);
     884           0 :         poff = SVAL(req->vwv+3, 0);
     885           0 :         pdisp = SVAL(req->vwv+4, 0);
     886             : 
     887           0 :         dcnt = SVAL(req->vwv+5, 0);
     888           0 :         doff = SVAL(req->vwv+6, 0);
     889           0 :         ddisp = SVAL(req->vwv+7, 0);
     890             : 
     891           0 :         state->received_param += pcnt;
     892           0 :         state->received_data += dcnt;
     893             : 
     894           0 :         if ((state->received_data > state->total_data) ||
     895           0 :             (state->received_param > state->total_param))
     896           0 :                 goto bad_param;
     897             : 
     898           0 :         if (pcnt) {
     899           0 :                 if (smb_buffer_oob(state->total_param, pdisp, pcnt)
     900           0 :                     || smb_buffer_oob(smb_len(req->inbuf), poff, pcnt)) {
     901           0 :                         goto bad_param;
     902             :                 }
     903           0 :                 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
     904             :         }
     905             : 
     906           0 :         if (dcnt) {
     907           0 :                 if (smb_buffer_oob(state->total_data, ddisp, dcnt)
     908           0 :                     || smb_buffer_oob(smb_len(req->inbuf), doff, dcnt)) {
     909           0 :                         goto bad_param;
     910             :                 }
     911           0 :                 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
     912             :         }
     913             : 
     914           0 :         if ((state->received_param < state->total_param) ||
     915           0 :             (state->received_data < state->total_data)) {
     916           0 :                 END_PROFILE(SMBtranss);
     917           0 :                 return;
     918             :         }
     919             : 
     920           0 :         talloc_steal(talloc_tos(), state);
     921             : 
     922           0 :         handle_trans(conn, req, state);
     923             : 
     924           0 :         DLIST_REMOVE(conn->pending_trans, state);
     925           0 :         SAFE_FREE(state->data);
     926           0 :         SAFE_FREE(state->param);
     927           0 :         TALLOC_FREE(state);
     928             : 
     929           0 :         END_PROFILE(SMBtranss);
     930           0 :         return;
     931             : 
     932           0 :   bad_param:
     933             : 
     934           0 :         DEBUG(0,("reply_transs: invalid trans parameters\n"));
     935           0 :         DLIST_REMOVE(conn->pending_trans, state);
     936           0 :         SAFE_FREE(state->data);
     937           0 :         SAFE_FREE(state->param);
     938           0 :         TALLOC_FREE(state);
     939           0 :         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     940           0 :         END_PROFILE(SMBtranss);
     941           0 :         return;
     942             : }

Generated by: LCOV version 1.13