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