| 1 | /*
|
|---|
| 2 | * Unix SMB/CIFS implementation.
|
|---|
| 3 | * RPC Pipe client / server routines
|
|---|
| 4 | * Copyright (C) Andrew Tridgell 1992-1998,
|
|---|
| 5 | * Largely re-written : 2005
|
|---|
| 6 | * Copyright (C) Jeremy Allison 1998 - 2005
|
|---|
| 7 | *
|
|---|
| 8 | * This program is free software; you can redistribute it and/or modify
|
|---|
| 9 | * it under the terms of the GNU General Public License as published by
|
|---|
| 10 | * the Free Software Foundation; either version 3 of the License, or
|
|---|
| 11 | * (at your option) any later version.
|
|---|
| 12 | *
|
|---|
| 13 | * This program is distributed in the hope that it will be useful,
|
|---|
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|---|
| 16 | * GNU General Public License for more details.
|
|---|
| 17 | *
|
|---|
| 18 | * You should have received a copy of the GNU General Public License
|
|---|
| 19 | * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|---|
| 20 | */
|
|---|
| 21 |
|
|---|
| 22 | #include "includes.h"
|
|---|
| 23 |
|
|---|
| 24 | #undef DBGC_CLASS
|
|---|
| 25 | #define DBGC_CLASS DBGC_RPC_SRV
|
|---|
| 26 |
|
|---|
| 27 | #define PIPE "\\PIPE\\"
|
|---|
| 28 | #define PIPELEN strlen(PIPE)
|
|---|
| 29 |
|
|---|
| 30 | static smb_np_struct *chain_p;
|
|---|
| 31 | static int pipes_open;
|
|---|
| 32 |
|
|---|
| 33 | /*
|
|---|
| 34 | * Sometimes I can't decide if I hate Windows printer driver
|
|---|
| 35 | * writers more than I hate the Windows spooler service driver
|
|---|
| 36 | * writers. This gets around a combination of bugs in the spooler
|
|---|
| 37 | * and the HP 8500 PCL driver that causes a spooler spin. JRA.
|
|---|
| 38 | *
|
|---|
| 39 | * bumped up from 20 -> 64 after viewing traffic from WordPerfect
|
|---|
| 40 | * 2002 running on NT 4.- SP6
|
|---|
| 41 | * bumped up from 64 -> 256 after viewing traffic from con2prt
|
|---|
| 42 | * for lots of printers on a WinNT 4.x SP6 box.
|
|---|
| 43 | */
|
|---|
| 44 |
|
|---|
| 45 | #ifndef MAX_OPEN_SPOOLSS_PIPES
|
|---|
| 46 | #define MAX_OPEN_SPOOLSS_PIPES 256
|
|---|
| 47 | #endif
|
|---|
| 48 | static int current_spoolss_pipes_open;
|
|---|
| 49 |
|
|---|
| 50 | static smb_np_struct *Pipes;
|
|---|
| 51 | static pipes_struct *InternalPipes;
|
|---|
| 52 | static struct bitmap *bmap;
|
|---|
| 53 |
|
|---|
| 54 | /* TODO
|
|---|
| 55 | * the following prototypes are declared here to avoid
|
|---|
| 56 | * code being moved about too much for a patch to be
|
|---|
| 57 | * disrupted / less obvious.
|
|---|
| 58 | *
|
|---|
| 59 | * these functions, and associated functions that they
|
|---|
| 60 | * call, should be moved behind a .so module-loading
|
|---|
| 61 | * system _anyway_. so that's the next step...
|
|---|
| 62 | */
|
|---|
| 63 |
|
|---|
| 64 | static ssize_t read_from_internal_pipe(void *np_conn, char *data, size_t n,
|
|---|
| 65 | bool *is_data_outstanding);
|
|---|
| 66 | static ssize_t write_to_internal_pipe(void *np_conn, char *data, size_t n);
|
|---|
| 67 | static bool close_internal_rpc_pipe_hnd(void *np_conn);
|
|---|
| 68 | static void *make_internal_rpc_pipe_p(const char *pipe_name,
|
|---|
| 69 | connection_struct *conn, uint16 vuid);
|
|---|
| 70 |
|
|---|
| 71 | /****************************************************************************
|
|---|
| 72 | Internal Pipe iterator functions.
|
|---|
| 73 | ****************************************************************************/
|
|---|
| 74 |
|
|---|
| 75 | pipes_struct *get_first_internal_pipe(void)
|
|---|
| 76 | {
|
|---|
| 77 | return InternalPipes;
|
|---|
| 78 | }
|
|---|
| 79 |
|
|---|
| 80 | pipes_struct *get_next_internal_pipe(pipes_struct *p)
|
|---|
| 81 | {
|
|---|
| 82 | return p->next;
|
|---|
| 83 | }
|
|---|
| 84 |
|
|---|
| 85 | /* this must be larger than the sum of the open files and directories */
|
|---|
| 86 | static int pipe_handle_offset;
|
|---|
| 87 |
|
|---|
| 88 | /****************************************************************************
|
|---|
| 89 | Set the pipe_handle_offset. Called from smbd/files.c
|
|---|
| 90 | ****************************************************************************/
|
|---|
| 91 |
|
|---|
| 92 | void set_pipe_handle_offset(int max_open_files)
|
|---|
| 93 | {
|
|---|
| 94 | if(max_open_files < 0x7000) {
|
|---|
| 95 | pipe_handle_offset = 0x7000;
|
|---|
| 96 | } else {
|
|---|
| 97 | pipe_handle_offset = max_open_files + 10; /* For safety. :-) */
|
|---|
| 98 | }
|
|---|
| 99 | }
|
|---|
| 100 |
|
|---|
| 101 | /****************************************************************************
|
|---|
| 102 | Reset pipe chain handle number.
|
|---|
| 103 | ****************************************************************************/
|
|---|
| 104 |
|
|---|
| 105 | void reset_chain_p(void)
|
|---|
| 106 | {
|
|---|
| 107 | chain_p = NULL;
|
|---|
| 108 | }
|
|---|
| 109 |
|
|---|
| 110 | /****************************************************************************
|
|---|
| 111 | Initialise pipe handle states.
|
|---|
| 112 | ****************************************************************************/
|
|---|
| 113 |
|
|---|
| 114 | void init_rpc_pipe_hnd(void)
|
|---|
| 115 | {
|
|---|
| 116 | bmap = bitmap_allocate(MAX_OPEN_PIPES);
|
|---|
| 117 | if (!bmap) {
|
|---|
| 118 | exit_server("out of memory in init_rpc_pipe_hnd");
|
|---|
| 119 | }
|
|---|
| 120 | }
|
|---|
| 121 |
|
|---|
| 122 | /****************************************************************************
|
|---|
| 123 | Initialise an outgoing packet.
|
|---|
| 124 | ****************************************************************************/
|
|---|
| 125 |
|
|---|
| 126 | static bool pipe_init_outgoing_data(pipes_struct *p)
|
|---|
| 127 | {
|
|---|
| 128 | output_data *o_data = &p->out_data;
|
|---|
| 129 |
|
|---|
| 130 | /* Reset the offset counters. */
|
|---|
| 131 | o_data->data_sent_length = 0;
|
|---|
| 132 | o_data->current_pdu_len = 0;
|
|---|
| 133 | o_data->current_pdu_sent = 0;
|
|---|
| 134 |
|
|---|
| 135 | memset(o_data->current_pdu, '\0', sizeof(o_data->current_pdu));
|
|---|
| 136 |
|
|---|
| 137 | /* Free any memory in the current return data buffer. */
|
|---|
| 138 | prs_mem_free(&o_data->rdata);
|
|---|
| 139 |
|
|---|
| 140 | /*
|
|---|
| 141 | * Initialize the outgoing RPC data buffer.
|
|---|
| 142 | * we will use this as the raw data area for replying to rpc requests.
|
|---|
| 143 | */
|
|---|
| 144 | if(!prs_init(&o_data->rdata, RPC_MAX_PDU_FRAG_LEN, p->mem_ctx, MARSHALL)) {
|
|---|
| 145 | DEBUG(0,("pipe_init_outgoing_data: malloc fail.\n"));
|
|---|
| 146 | return False;
|
|---|
| 147 | }
|
|---|
| 148 |
|
|---|
| 149 | return True;
|
|---|
| 150 | }
|
|---|
| 151 |
|
|---|
| 152 | /****************************************************************************
|
|---|
| 153 | Find first available pipe slot.
|
|---|
| 154 | ****************************************************************************/
|
|---|
| 155 |
|
|---|
| 156 | smb_np_struct *open_rpc_pipe_p(const char *pipe_name,
|
|---|
| 157 | connection_struct *conn, uint16 vuid)
|
|---|
| 158 | {
|
|---|
| 159 | int i;
|
|---|
| 160 | smb_np_struct *p, *p_it;
|
|---|
| 161 | static int next_pipe;
|
|---|
| 162 | bool is_spoolss_pipe = False;
|
|---|
| 163 |
|
|---|
| 164 | DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
|
|---|
| 165 | pipe_name, pipes_open));
|
|---|
| 166 |
|
|---|
| 167 | if (strstr(pipe_name, "spoolss")) {
|
|---|
| 168 | is_spoolss_pipe = True;
|
|---|
| 169 | }
|
|---|
| 170 |
|
|---|
| 171 | if (is_spoolss_pipe && current_spoolss_pipes_open >= MAX_OPEN_SPOOLSS_PIPES) {
|
|---|
| 172 | DEBUG(10,("open_rpc_pipe_p: spooler bug workaround. Denying open on pipe %s\n",
|
|---|
| 173 | pipe_name ));
|
|---|
| 174 | return NULL;
|
|---|
| 175 | }
|
|---|
| 176 |
|
|---|
| 177 | /* not repeating pipe numbers makes it easier to track things in
|
|---|
| 178 | log files and prevents client bugs where pipe numbers are reused
|
|---|
| 179 | over connection restarts */
|
|---|
| 180 |
|
|---|
| 181 | if (next_pipe == 0) {
|
|---|
| 182 | next_pipe = (sys_getpid() ^ time(NULL)) % MAX_OPEN_PIPES;
|
|---|
| 183 | }
|
|---|
| 184 |
|
|---|
| 185 | i = bitmap_find(bmap, next_pipe);
|
|---|
| 186 |
|
|---|
| 187 | if (i == -1) {
|
|---|
| 188 | DEBUG(0,("ERROR! Out of pipe structures\n"));
|
|---|
| 189 | return NULL;
|
|---|
| 190 | }
|
|---|
| 191 |
|
|---|
| 192 | next_pipe = (i+1) % MAX_OPEN_PIPES;
|
|---|
| 193 |
|
|---|
| 194 | for (p = Pipes; p; p = p->next) {
|
|---|
| 195 | DEBUG(5,("open_rpc_pipe_p: name %s pnum=%x\n", p->name, p->pnum));
|
|---|
| 196 | }
|
|---|
| 197 |
|
|---|
| 198 | p = talloc(NULL, smb_np_struct);
|
|---|
| 199 | if (!p) {
|
|---|
| 200 | DEBUG(0,("ERROR! no memory for smb_np_struct!\n"));
|
|---|
| 201 | return NULL;
|
|---|
| 202 | }
|
|---|
| 203 |
|
|---|
| 204 | ZERO_STRUCTP(p);
|
|---|
| 205 |
|
|---|
| 206 | p->name = talloc_strdup(p, pipe_name);
|
|---|
| 207 | if (p->name == NULL) {
|
|---|
| 208 | TALLOC_FREE(p);
|
|---|
| 209 | DEBUG(0,("ERROR! no memory for pipe name!\n"));
|
|---|
| 210 | return NULL;
|
|---|
| 211 | }
|
|---|
| 212 |
|
|---|
| 213 | /* add a dso mechanism instead of this, here */
|
|---|
| 214 |
|
|---|
| 215 | p->namedpipe_create = make_internal_rpc_pipe_p;
|
|---|
| 216 | p->namedpipe_read = read_from_internal_pipe;
|
|---|
| 217 | p->namedpipe_write = write_to_internal_pipe;
|
|---|
| 218 | p->namedpipe_close = close_internal_rpc_pipe_hnd;
|
|---|
| 219 |
|
|---|
| 220 | p->np_state = p->namedpipe_create(pipe_name, conn, vuid);
|
|---|
| 221 |
|
|---|
| 222 | if (p->np_state == NULL) {
|
|---|
| 223 | DEBUG(0,("open_rpc_pipe_p: make_internal_rpc_pipe_p failed.\n"));
|
|---|
| 224 | SAFE_FREE(p);
|
|---|
| 225 | return NULL;
|
|---|
| 226 | }
|
|---|
| 227 |
|
|---|
| 228 | DLIST_ADD(Pipes, p);
|
|---|
| 229 |
|
|---|
| 230 | /*
|
|---|
| 231 | * Initialize the incoming RPC data buffer with one PDU worth of memory.
|
|---|
| 232 | * We cheat here and say we're marshalling, as we intend to add incoming
|
|---|
| 233 | * data directly into the prs_struct and we want it to auto grow. We will
|
|---|
| 234 | * change the type to UNMARSALLING before processing the stream.
|
|---|
| 235 | */
|
|---|
| 236 |
|
|---|
| 237 | bitmap_set(bmap, i);
|
|---|
| 238 | i += pipe_handle_offset;
|
|---|
| 239 |
|
|---|
| 240 | pipes_open++;
|
|---|
| 241 |
|
|---|
| 242 | p->pnum = i;
|
|---|
| 243 |
|
|---|
| 244 | p->open = True;
|
|---|
| 245 | p->device_state = 0;
|
|---|
| 246 | p->priority = 0;
|
|---|
| 247 | p->conn = conn;
|
|---|
| 248 | p->vuid = vuid;
|
|---|
| 249 |
|
|---|
| 250 | p->max_trans_reply = 0;
|
|---|
| 251 |
|
|---|
| 252 | DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n",
|
|---|
| 253 | pipe_name, i, pipes_open));
|
|---|
| 254 |
|
|---|
| 255 | chain_p = p;
|
|---|
| 256 |
|
|---|
| 257 | /* Iterate over p_it as a temp variable, to display all open pipes */
|
|---|
| 258 | for (p_it = Pipes; p_it; p_it = p_it->next) {
|
|---|
| 259 | DEBUG(5,("open pipes: name %s pnum=%x\n", p_it->name, p_it->pnum));
|
|---|
| 260 | }
|
|---|
| 261 |
|
|---|
| 262 | return chain_p;
|
|---|
| 263 | }
|
|---|
| 264 |
|
|---|
| 265 | /****************************************************************************
|
|---|
| 266 | Make an internal namedpipes structure
|
|---|
| 267 | ****************************************************************************/
|
|---|
| 268 |
|
|---|
| 269 | static void *make_internal_rpc_pipe_p(const char *pipe_name,
|
|---|
| 270 | connection_struct *conn, uint16 vuid)
|
|---|
| 271 | {
|
|---|
| 272 | pipes_struct *p;
|
|---|
| 273 | user_struct *vuser = get_valid_user_struct(vuid);
|
|---|
| 274 |
|
|---|
| 275 | DEBUG(4,("Create pipe requested %s\n", pipe_name));
|
|---|
| 276 |
|
|---|
| 277 | if (!vuser && vuid != UID_FIELD_INVALID) {
|
|---|
| 278 | DEBUG(0,("ERROR! vuid %d did not map to a valid vuser struct!\n", vuid));
|
|---|
| 279 | return NULL;
|
|---|
| 280 | }
|
|---|
| 281 |
|
|---|
| 282 | p = SMB_MALLOC_P(pipes_struct);
|
|---|
| 283 |
|
|---|
| 284 | if (!p) {
|
|---|
| 285 | DEBUG(0,("ERROR! no memory for pipes_struct!\n"));
|
|---|
| 286 | return NULL;
|
|---|
| 287 | }
|
|---|
| 288 |
|
|---|
| 289 | ZERO_STRUCTP(p);
|
|---|
| 290 |
|
|---|
| 291 | if ((p->mem_ctx = talloc_init("pipe %s %p", pipe_name, p)) == NULL) {
|
|---|
| 292 | DEBUG(0,("open_rpc_pipe_p: talloc_init failed.\n"));
|
|---|
| 293 | SAFE_FREE(p);
|
|---|
| 294 | return NULL;
|
|---|
| 295 | }
|
|---|
| 296 |
|
|---|
| 297 | if ((p->pipe_state_mem_ctx = talloc_init("pipe_state %s %p", pipe_name, p)) == NULL) {
|
|---|
| 298 | DEBUG(0,("open_rpc_pipe_p: talloc_init failed.\n"));
|
|---|
| 299 | talloc_destroy(p->mem_ctx);
|
|---|
| 300 | SAFE_FREE(p);
|
|---|
| 301 | return NULL;
|
|---|
| 302 | }
|
|---|
| 303 |
|
|---|
| 304 | if (!init_pipe_handle_list(p, pipe_name)) {
|
|---|
| 305 | DEBUG(0,("open_rpc_pipe_p: init_pipe_handles failed.\n"));
|
|---|
| 306 | talloc_destroy(p->mem_ctx);
|
|---|
| 307 | talloc_destroy(p->pipe_state_mem_ctx);
|
|---|
| 308 | SAFE_FREE(p);
|
|---|
| 309 | return NULL;
|
|---|
| 310 | }
|
|---|
| 311 |
|
|---|
| 312 | /*
|
|---|
| 313 | * Initialize the incoming RPC data buffer with one PDU worth of memory.
|
|---|
| 314 | * We cheat here and say we're marshalling, as we intend to add incoming
|
|---|
| 315 | * data directly into the prs_struct and we want it to auto grow. We will
|
|---|
| 316 | * change the type to UNMARSALLING before processing the stream.
|
|---|
| 317 | */
|
|---|
| 318 |
|
|---|
| 319 | if(!prs_init(&p->in_data.data, RPC_MAX_PDU_FRAG_LEN, p->mem_ctx, MARSHALL)) {
|
|---|
| 320 | DEBUG(0,("open_rpc_pipe_p: malloc fail for in_data struct.\n"));
|
|---|
| 321 | talloc_destroy(p->mem_ctx);
|
|---|
| 322 | talloc_destroy(p->pipe_state_mem_ctx);
|
|---|
| 323 | close_policy_by_pipe(p);
|
|---|
| 324 | SAFE_FREE(p);
|
|---|
| 325 | return NULL;
|
|---|
| 326 | }
|
|---|
| 327 |
|
|---|
| 328 | DLIST_ADD(InternalPipes, p);
|
|---|
| 329 |
|
|---|
| 330 | p->conn = conn;
|
|---|
| 331 |
|
|---|
| 332 | p->vuid = vuid;
|
|---|
| 333 |
|
|---|
| 334 | p->endian = RPC_LITTLE_ENDIAN;
|
|---|
| 335 |
|
|---|
| 336 | ZERO_STRUCT(p->pipe_user);
|
|---|
| 337 |
|
|---|
| 338 | p->pipe_user.ut.uid = (uid_t)-1;
|
|---|
| 339 | p->pipe_user.ut.gid = (gid_t)-1;
|
|---|
| 340 |
|
|---|
| 341 | /* Store the session key and NT_TOKEN */
|
|---|
| 342 | if (vuser) {
|
|---|
| 343 | p->session_key = data_blob(vuser->session_key.data, vuser->session_key.length);
|
|---|
| 344 | p->pipe_user.nt_user_token = dup_nt_token(
|
|---|
| 345 | NULL, vuser->nt_user_token);
|
|---|
| 346 | }
|
|---|
| 347 |
|
|---|
| 348 | /*
|
|---|
| 349 | * Initialize the outgoing RPC data buffer with no memory.
|
|---|
| 350 | */
|
|---|
| 351 | prs_init_empty(&p->out_data.rdata, p->mem_ctx, MARSHALL);
|
|---|
| 352 |
|
|---|
| 353 | fstrcpy(p->name, pipe_name);
|
|---|
| 354 |
|
|---|
| 355 | DEBUG(4,("Created internal pipe %s (pipes_open=%d)\n",
|
|---|
| 356 | pipe_name, pipes_open));
|
|---|
| 357 |
|
|---|
| 358 | return (void*)p;
|
|---|
| 359 | }
|
|---|
| 360 |
|
|---|
| 361 | /****************************************************************************
|
|---|
| 362 | Sets the fault state on incoming packets.
|
|---|
| 363 | ****************************************************************************/
|
|---|
| 364 |
|
|---|
| 365 | static void set_incoming_fault(pipes_struct *p)
|
|---|
| 366 | {
|
|---|
| 367 | prs_mem_free(&p->in_data.data);
|
|---|
| 368 | p->in_data.pdu_needed_len = 0;
|
|---|
| 369 | p->in_data.pdu_received_len = 0;
|
|---|
| 370 | p->fault_state = True;
|
|---|
| 371 | DEBUG(10,("set_incoming_fault: Setting fault state on pipe %s : vuid = 0x%x\n",
|
|---|
| 372 | p->name, p->vuid ));
|
|---|
| 373 | }
|
|---|
| 374 |
|
|---|
| 375 | /****************************************************************************
|
|---|
| 376 | Ensures we have at least RPC_HEADER_LEN amount of data in the incoming buffer.
|
|---|
| 377 | ****************************************************************************/
|
|---|
| 378 |
|
|---|
| 379 | static ssize_t fill_rpc_header(pipes_struct *p, char *data, size_t data_to_copy)
|
|---|
| 380 | {
|
|---|
| 381 | size_t len_needed_to_complete_hdr = MIN(data_to_copy, RPC_HEADER_LEN - p->in_data.pdu_received_len);
|
|---|
| 382 |
|
|---|
| 383 | DEBUG(10,("fill_rpc_header: data_to_copy = %u, len_needed_to_complete_hdr = %u, receive_len = %u\n",
|
|---|
| 384 | (unsigned int)data_to_copy, (unsigned int)len_needed_to_complete_hdr,
|
|---|
| 385 | (unsigned int)p->in_data.pdu_received_len ));
|
|---|
| 386 |
|
|---|
| 387 | memcpy((char *)&p->in_data.current_in_pdu[p->in_data.pdu_received_len], data, len_needed_to_complete_hdr);
|
|---|
| 388 | p->in_data.pdu_received_len += len_needed_to_complete_hdr;
|
|---|
| 389 |
|
|---|
| 390 | return (ssize_t)len_needed_to_complete_hdr;
|
|---|
| 391 | }
|
|---|
| 392 |
|
|---|
| 393 | /****************************************************************************
|
|---|
| 394 | Unmarshalls a new PDU header. Assumes the raw header data is in current_in_pdu.
|
|---|
| 395 | ****************************************************************************/
|
|---|
| 396 |
|
|---|
| 397 | static ssize_t unmarshall_rpc_header(pipes_struct *p)
|
|---|
| 398 | {
|
|---|
| 399 | /*
|
|---|
| 400 | * Unmarshall the header to determine the needed length.
|
|---|
| 401 | */
|
|---|
| 402 |
|
|---|
| 403 | prs_struct rpc_in;
|
|---|
| 404 |
|
|---|
| 405 | if(p->in_data.pdu_received_len != RPC_HEADER_LEN) {
|
|---|
| 406 | DEBUG(0,("unmarshall_rpc_header: assert on rpc header length failed.\n"));
|
|---|
| 407 | set_incoming_fault(p);
|
|---|
| 408 | return -1;
|
|---|
| 409 | }
|
|---|
| 410 |
|
|---|
| 411 | prs_init_empty( &rpc_in, p->mem_ctx, UNMARSHALL);
|
|---|
| 412 | prs_set_endian_data( &rpc_in, p->endian);
|
|---|
| 413 |
|
|---|
| 414 | prs_give_memory( &rpc_in, (char *)&p->in_data.current_in_pdu[0],
|
|---|
| 415 | p->in_data.pdu_received_len, False);
|
|---|
| 416 |
|
|---|
| 417 | /*
|
|---|
| 418 | * Unmarshall the header as this will tell us how much
|
|---|
| 419 | * data we need to read to get the complete pdu.
|
|---|
| 420 | * This also sets the endian flag in rpc_in.
|
|---|
| 421 | */
|
|---|
| 422 |
|
|---|
| 423 | if(!smb_io_rpc_hdr("", &p->hdr, &rpc_in, 0)) {
|
|---|
| 424 | DEBUG(0,("unmarshall_rpc_header: failed to unmarshall RPC_HDR.\n"));
|
|---|
| 425 | set_incoming_fault(p);
|
|---|
| 426 | prs_mem_free(&rpc_in);
|
|---|
| 427 | return -1;
|
|---|
| 428 | }
|
|---|
| 429 |
|
|---|
| 430 | /*
|
|---|
| 431 | * Validate the RPC header.
|
|---|
| 432 | */
|
|---|
| 433 |
|
|---|
| 434 | if(p->hdr.major != 5 && p->hdr.minor != 0) {
|
|---|
| 435 | DEBUG(0,("unmarshall_rpc_header: invalid major/minor numbers in RPC_HDR.\n"));
|
|---|
| 436 | set_incoming_fault(p);
|
|---|
| 437 | prs_mem_free(&rpc_in);
|
|---|
| 438 | return -1;
|
|---|
| 439 | }
|
|---|
| 440 |
|
|---|
| 441 | /*
|
|---|
| 442 | * If there's not data in the incoming buffer this should be the start of a new RPC.
|
|---|
| 443 | */
|
|---|
| 444 |
|
|---|
| 445 | if(prs_offset(&p->in_data.data) == 0) {
|
|---|
| 446 |
|
|---|
| 447 | /*
|
|---|
| 448 | * AS/U doesn't set FIRST flag in a BIND packet it seems.
|
|---|
| 449 | */
|
|---|
| 450 |
|
|---|
| 451 | if ((p->hdr.pkt_type == RPC_REQUEST) && !(p->hdr.flags & RPC_FLG_FIRST)) {
|
|---|
| 452 | /*
|
|---|
| 453 | * Ensure that the FIRST flag is set. If not then we have
|
|---|
| 454 | * a stream missmatch.
|
|---|
| 455 | */
|
|---|
| 456 |
|
|---|
| 457 | DEBUG(0,("unmarshall_rpc_header: FIRST flag not set in first PDU !\n"));
|
|---|
| 458 | set_incoming_fault(p);
|
|---|
| 459 | prs_mem_free(&rpc_in);
|
|---|
| 460 | return -1;
|
|---|
| 461 | }
|
|---|
| 462 |
|
|---|
| 463 | /*
|
|---|
| 464 | * If this is the first PDU then set the endianness
|
|---|
| 465 | * flag in the pipe. We will need this when parsing all
|
|---|
| 466 | * data in this RPC.
|
|---|
| 467 | */
|
|---|
| 468 |
|
|---|
| 469 | p->endian = rpc_in.bigendian_data;
|
|---|
| 470 |
|
|---|
| 471 | DEBUG(5,("unmarshall_rpc_header: using %sendian RPC\n",
|
|---|
| 472 | p->endian == RPC_LITTLE_ENDIAN ? "little-" : "big-" ));
|
|---|
| 473 |
|
|---|
| 474 | } else {
|
|---|
| 475 |
|
|---|
| 476 | /*
|
|---|
| 477 | * If this is *NOT* the first PDU then check the endianness
|
|---|
| 478 | * flag in the pipe is the same as that in the PDU.
|
|---|
| 479 | */
|
|---|
| 480 |
|
|---|
| 481 | if (p->endian != rpc_in.bigendian_data) {
|
|---|
| 482 | DEBUG(0,("unmarshall_rpc_header: FIRST endianness flag (%d) different in next PDU !\n", (int)p->endian));
|
|---|
| 483 | set_incoming_fault(p);
|
|---|
| 484 | prs_mem_free(&rpc_in);
|
|---|
| 485 | return -1;
|
|---|
| 486 | }
|
|---|
| 487 | }
|
|---|
| 488 |
|
|---|
| 489 | /*
|
|---|
| 490 | * Ensure that the pdu length is sane.
|
|---|
| 491 | */
|
|---|
| 492 |
|
|---|
| 493 | if((p->hdr.frag_len < RPC_HEADER_LEN) || (p->hdr.frag_len > RPC_MAX_PDU_FRAG_LEN)) {
|
|---|
| 494 | DEBUG(0,("unmarshall_rpc_header: assert on frag length failed.\n"));
|
|---|
| 495 | set_incoming_fault(p);
|
|---|
| 496 | prs_mem_free(&rpc_in);
|
|---|
| 497 | return -1;
|
|---|
| 498 | }
|
|---|
| 499 |
|
|---|
| 500 | DEBUG(10,("unmarshall_rpc_header: type = %u, flags = %u\n", (unsigned int)p->hdr.pkt_type,
|
|---|
| 501 | (unsigned int)p->hdr.flags ));
|
|---|
| 502 |
|
|---|
| 503 | p->in_data.pdu_needed_len = (uint32)p->hdr.frag_len - RPC_HEADER_LEN;
|
|---|
| 504 |
|
|---|
| 505 | prs_mem_free(&rpc_in);
|
|---|
| 506 |
|
|---|
| 507 | return 0; /* No extra data processed. */
|
|---|
| 508 | }
|
|---|
| 509 |
|
|---|
| 510 | /****************************************************************************
|
|---|
| 511 | Call this to free any talloc'ed memory. Do this before and after processing
|
|---|
| 512 | a complete PDU.
|
|---|
| 513 | ****************************************************************************/
|
|---|
| 514 |
|
|---|
| 515 | static void free_pipe_context(pipes_struct *p)
|
|---|
| 516 | {
|
|---|
| 517 | if (p->mem_ctx) {
|
|---|
| 518 | DEBUG(3,("free_pipe_context: destroying talloc pool of size "
|
|---|
| 519 | "%lu\n", (unsigned long)talloc_total_size(p->mem_ctx) ));
|
|---|
| 520 | talloc_free_children(p->mem_ctx);
|
|---|
| 521 | } else {
|
|---|
| 522 | p->mem_ctx = talloc_init("pipe %s %p", p->name, p);
|
|---|
| 523 | if (p->mem_ctx == NULL) {
|
|---|
| 524 | p->fault_state = True;
|
|---|
| 525 | }
|
|---|
| 526 | }
|
|---|
| 527 | }
|
|---|
| 528 |
|
|---|
| 529 | /****************************************************************************
|
|---|
| 530 | Processes a request pdu. This will do auth processing if needed, and
|
|---|
| 531 | appends the data into the complete stream if the LAST flag is not set.
|
|---|
| 532 | ****************************************************************************/
|
|---|
| 533 |
|
|---|
| 534 | static bool process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
|
|---|
| 535 | {
|
|---|
| 536 | uint32 ss_padding_len = 0;
|
|---|
| 537 | size_t data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
|
|---|
| 538 | (p->hdr.auth_len ? RPC_HDR_AUTH_LEN : 0) - p->hdr.auth_len;
|
|---|
| 539 |
|
|---|
| 540 | if(!p->pipe_bound) {
|
|---|
| 541 | DEBUG(0,("process_request_pdu: rpc request with no bind.\n"));
|
|---|
| 542 | set_incoming_fault(p);
|
|---|
| 543 | return False;
|
|---|
| 544 | }
|
|---|
| 545 |
|
|---|
| 546 | /*
|
|---|
| 547 | * Check if we need to do authentication processing.
|
|---|
| 548 | * This is only done on requests, not binds.
|
|---|
| 549 | */
|
|---|
| 550 |
|
|---|
| 551 | /*
|
|---|
| 552 | * Read the RPC request header.
|
|---|
| 553 | */
|
|---|
| 554 |
|
|---|
| 555 | if(!smb_io_rpc_hdr_req("req", &p->hdr_req, rpc_in_p, 0)) {
|
|---|
| 556 | DEBUG(0,("process_request_pdu: failed to unmarshall RPC_HDR_REQ.\n"));
|
|---|
| 557 | set_incoming_fault(p);
|
|---|
| 558 | return False;
|
|---|
| 559 | }
|
|---|
| 560 |
|
|---|
| 561 | switch(p->auth.auth_type) {
|
|---|
| 562 | case PIPE_AUTH_TYPE_NONE:
|
|---|
| 563 | break;
|
|---|
| 564 |
|
|---|
| 565 | case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
|
|---|
| 566 | case PIPE_AUTH_TYPE_NTLMSSP:
|
|---|
| 567 | {
|
|---|
| 568 | NTSTATUS status;
|
|---|
| 569 | if(!api_pipe_ntlmssp_auth_process(p, rpc_in_p, &ss_padding_len, &status)) {
|
|---|
| 570 | DEBUG(0,("process_request_pdu: failed to do auth processing.\n"));
|
|---|
| 571 | DEBUG(0,("process_request_pdu: error was %s.\n", nt_errstr(status) ));
|
|---|
| 572 | set_incoming_fault(p);
|
|---|
| 573 | return False;
|
|---|
| 574 | }
|
|---|
| 575 | break;
|
|---|
| 576 | }
|
|---|
| 577 |
|
|---|
| 578 | case PIPE_AUTH_TYPE_SCHANNEL:
|
|---|
| 579 | if (!api_pipe_schannel_process(p, rpc_in_p, &ss_padding_len)) {
|
|---|
| 580 | DEBUG(3,("process_request_pdu: failed to do schannel processing.\n"));
|
|---|
| 581 | set_incoming_fault(p);
|
|---|
| 582 | return False;
|
|---|
| 583 | }
|
|---|
| 584 | break;
|
|---|
| 585 |
|
|---|
| 586 | default:
|
|---|
| 587 | DEBUG(0,("process_request_pdu: unknown auth type %u set.\n", (unsigned int)p->auth.auth_type ));
|
|---|
| 588 | set_incoming_fault(p);
|
|---|
| 589 | return False;
|
|---|
| 590 | }
|
|---|
| 591 |
|
|---|
| 592 | /* Now we've done the sign/seal we can remove any padding data. */
|
|---|
| 593 | if (data_len > ss_padding_len) {
|
|---|
| 594 | data_len -= ss_padding_len;
|
|---|
| 595 | }
|
|---|
| 596 |
|
|---|
| 597 | /*
|
|---|
| 598 | * Check the data length doesn't go over the 15Mb limit.
|
|---|
| 599 | * increased after observing a bug in the Windows NT 4.0 SP6a
|
|---|
| 600 | * spoolsv.exe when the response to a GETPRINTERDRIVER2 RPC
|
|---|
| 601 | * will not fit in the initial buffer of size 0x1068 --jerry 22/01/2002
|
|---|
| 602 | */
|
|---|
| 603 |
|
|---|
| 604 | if(prs_offset(&p->in_data.data) + data_len > MAX_RPC_DATA_SIZE) {
|
|---|
| 605 | DEBUG(0,("process_request_pdu: rpc data buffer too large (%u) + (%u)\n",
|
|---|
| 606 | (unsigned int)prs_data_size(&p->in_data.data), (unsigned int)data_len ));
|
|---|
| 607 | set_incoming_fault(p);
|
|---|
| 608 | return False;
|
|---|
| 609 | }
|
|---|
| 610 |
|
|---|
| 611 | /*
|
|---|
| 612 | * Append the data portion into the buffer and return.
|
|---|
| 613 | */
|
|---|
| 614 |
|
|---|
| 615 | if(!prs_append_some_prs_data(&p->in_data.data, rpc_in_p, prs_offset(rpc_in_p), data_len)) {
|
|---|
| 616 | DEBUG(0,("process_request_pdu: Unable to append data size %u to parse buffer of size %u.\n",
|
|---|
| 617 | (unsigned int)data_len, (unsigned int)prs_data_size(&p->in_data.data) ));
|
|---|
| 618 | set_incoming_fault(p);
|
|---|
| 619 | return False;
|
|---|
| 620 | }
|
|---|
| 621 |
|
|---|
| 622 | if(p->hdr.flags & RPC_FLG_LAST) {
|
|---|
| 623 | bool ret = False;
|
|---|
| 624 | /*
|
|---|
| 625 | * Ok - we finally have a complete RPC stream.
|
|---|
| 626 | * Call the rpc command to process it.
|
|---|
| 627 | */
|
|---|
| 628 |
|
|---|
| 629 | /*
|
|---|
| 630 | * Ensure the internal prs buffer size is *exactly* the same
|
|---|
| 631 | * size as the current offset.
|
|---|
| 632 | */
|
|---|
| 633 |
|
|---|
| 634 | if(!prs_set_buffer_size(&p->in_data.data, prs_offset(&p->in_data.data))) {
|
|---|
| 635 | DEBUG(0,("process_request_pdu: Call to prs_set_buffer_size failed!\n"));
|
|---|
| 636 | set_incoming_fault(p);
|
|---|
| 637 | return False;
|
|---|
| 638 | }
|
|---|
| 639 |
|
|---|
| 640 | /*
|
|---|
| 641 | * Set the parse offset to the start of the data and set the
|
|---|
| 642 | * prs_struct to UNMARSHALL.
|
|---|
| 643 | */
|
|---|
| 644 |
|
|---|
| 645 | prs_set_offset(&p->in_data.data, 0);
|
|---|
| 646 | prs_switch_type(&p->in_data.data, UNMARSHALL);
|
|---|
| 647 |
|
|---|
| 648 | /*
|
|---|
| 649 | * Process the complete data stream here.
|
|---|
| 650 | */
|
|---|
| 651 |
|
|---|
| 652 | free_pipe_context(p);
|
|---|
| 653 |
|
|---|
| 654 | if(pipe_init_outgoing_data(p)) {
|
|---|
| 655 | ret = api_pipe_request(p);
|
|---|
| 656 | }
|
|---|
| 657 |
|
|---|
| 658 | free_pipe_context(p);
|
|---|
| 659 |
|
|---|
| 660 | /*
|
|---|
| 661 | * We have consumed the whole data stream. Set back to
|
|---|
| 662 | * marshalling and set the offset back to the start of
|
|---|
| 663 | * the buffer to re-use it (we could also do a prs_mem_free()
|
|---|
| 664 | * and then re_init on the next start of PDU. Not sure which
|
|---|
| 665 | * is best here.... JRA.
|
|---|
| 666 | */
|
|---|
| 667 |
|
|---|
| 668 | prs_switch_type(&p->in_data.data, MARSHALL);
|
|---|
| 669 | prs_set_offset(&p->in_data.data, 0);
|
|---|
| 670 | return ret;
|
|---|
| 671 | }
|
|---|
| 672 |
|
|---|
| 673 | return True;
|
|---|
| 674 | }
|
|---|
| 675 |
|
|---|
| 676 | /****************************************************************************
|
|---|
| 677 | Processes a finished PDU stored in current_in_pdu. The RPC_HEADER has
|
|---|
| 678 | already been parsed and stored in p->hdr.
|
|---|
| 679 | ****************************************************************************/
|
|---|
| 680 |
|
|---|
| 681 | static void process_complete_pdu(pipes_struct *p)
|
|---|
| 682 | {
|
|---|
| 683 | prs_struct rpc_in;
|
|---|
| 684 | size_t data_len = p->in_data.pdu_received_len - RPC_HEADER_LEN;
|
|---|
| 685 | char *data_p = (char *)&p->in_data.current_in_pdu[RPC_HEADER_LEN];
|
|---|
| 686 | bool reply = False;
|
|---|
| 687 |
|
|---|
| 688 | if(p->fault_state) {
|
|---|
| 689 | DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n",
|
|---|
| 690 | p->name ));
|
|---|
| 691 | set_incoming_fault(p);
|
|---|
| 692 | setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
|
|---|
| 693 | return;
|
|---|
| 694 | }
|
|---|
| 695 |
|
|---|
| 696 | prs_init_empty( &rpc_in, p->mem_ctx, UNMARSHALL);
|
|---|
| 697 |
|
|---|
| 698 | /*
|
|---|
| 699 | * Ensure we're using the corrent endianness for both the
|
|---|
| 700 | * RPC header flags and the raw data we will be reading from.
|
|---|
| 701 | */
|
|---|
| 702 |
|
|---|
| 703 | prs_set_endian_data( &rpc_in, p->endian);
|
|---|
| 704 | prs_set_endian_data( &p->in_data.data, p->endian);
|
|---|
| 705 |
|
|---|
| 706 | prs_give_memory( &rpc_in, data_p, (uint32)data_len, False);
|
|---|
| 707 |
|
|---|
| 708 | DEBUG(10,("process_complete_pdu: processing packet type %u\n",
|
|---|
| 709 | (unsigned int)p->hdr.pkt_type ));
|
|---|
| 710 |
|
|---|
| 711 | switch (p->hdr.pkt_type) {
|
|---|
| 712 | case RPC_REQUEST:
|
|---|
| 713 | reply = process_request_pdu(p, &rpc_in);
|
|---|
| 714 | break;
|
|---|
| 715 |
|
|---|
| 716 | case RPC_PING: /* CL request - ignore... */
|
|---|
| 717 | DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n",
|
|---|
| 718 | (unsigned int)p->hdr.pkt_type, p->name));
|
|---|
| 719 | break;
|
|---|
| 720 |
|
|---|
| 721 | case RPC_RESPONSE: /* No responses here. */
|
|---|
| 722 | DEBUG(0,("process_complete_pdu: Error. RPC_RESPONSE received from client on pipe %s.\n",
|
|---|
| 723 | p->name ));
|
|---|
| 724 | break;
|
|---|
| 725 |
|
|---|
| 726 | case RPC_FAULT:
|
|---|
| 727 | case RPC_WORKING: /* CL request - reply to a ping when a call in process. */
|
|---|
| 728 | case RPC_NOCALL: /* CL - server reply to a ping call. */
|
|---|
| 729 | case RPC_REJECT:
|
|---|
| 730 | case RPC_ACK:
|
|---|
| 731 | case RPC_CL_CANCEL:
|
|---|
| 732 | case RPC_FACK:
|
|---|
| 733 | case RPC_CANCEL_ACK:
|
|---|
| 734 | DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n",
|
|---|
| 735 | (unsigned int)p->hdr.pkt_type, p->name));
|
|---|
| 736 | break;
|
|---|
| 737 |
|
|---|
| 738 | case RPC_BIND:
|
|---|
| 739 | /*
|
|---|
| 740 | * We assume that a pipe bind is only in one pdu.
|
|---|
| 741 | */
|
|---|
| 742 | if(pipe_init_outgoing_data(p)) {
|
|---|
| 743 | reply = api_pipe_bind_req(p, &rpc_in);
|
|---|
| 744 | }
|
|---|
| 745 | break;
|
|---|
| 746 |
|
|---|
| 747 | case RPC_BINDACK:
|
|---|
| 748 | case RPC_BINDNACK:
|
|---|
| 749 | DEBUG(0,("process_complete_pdu: Error. RPC_BINDACK/RPC_BINDNACK packet type %u received on pipe %s.\n",
|
|---|
| 750 | (unsigned int)p->hdr.pkt_type, p->name));
|
|---|
| 751 | break;
|
|---|
| 752 |
|
|---|
| 753 |
|
|---|
| 754 | case RPC_ALTCONT:
|
|---|
| 755 | /*
|
|---|
| 756 | * We assume that a pipe bind is only in one pdu.
|
|---|
| 757 | */
|
|---|
| 758 | if(pipe_init_outgoing_data(p)) {
|
|---|
| 759 | reply = api_pipe_alter_context(p, &rpc_in);
|
|---|
| 760 | }
|
|---|
| 761 | break;
|
|---|
| 762 |
|
|---|
| 763 | case RPC_ALTCONTRESP:
|
|---|
| 764 | DEBUG(0,("process_complete_pdu: Error. RPC_ALTCONTRESP on pipe %s: Should only be server -> client.\n",
|
|---|
| 765 | p->name));
|
|---|
| 766 | break;
|
|---|
| 767 |
|
|---|
| 768 | case RPC_AUTH3:
|
|---|
| 769 | /*
|
|---|
| 770 | * The third packet in an NTLMSSP auth exchange.
|
|---|
| 771 | */
|
|---|
| 772 | if(pipe_init_outgoing_data(p)) {
|
|---|
| 773 | reply = api_pipe_bind_auth3(p, &rpc_in);
|
|---|
| 774 | }
|
|---|
| 775 | break;
|
|---|
| 776 |
|
|---|
| 777 | case RPC_SHUTDOWN:
|
|---|
| 778 | DEBUG(0,("process_complete_pdu: Error. RPC_SHUTDOWN on pipe %s: Should only be server -> client.\n",
|
|---|
| 779 | p->name));
|
|---|
| 780 | break;
|
|---|
| 781 |
|
|---|
| 782 | case RPC_CO_CANCEL:
|
|---|
| 783 | /* For now just free all client data and continue processing. */
|
|---|
| 784 | DEBUG(3,("process_complete_pdu: RPC_ORPHANED. Abandoning rpc call.\n"));
|
|---|
| 785 | /* As we never do asynchronous RPC serving, we can never cancel a
|
|---|
| 786 | call (as far as I know). If we ever did we'd have to send a cancel_ack
|
|---|
| 787 | reply. For now, just free all client data and continue processing. */
|
|---|
| 788 | reply = True;
|
|---|
| 789 | break;
|
|---|
| 790 | #if 0
|
|---|
| 791 | /* Enable this if we're doing async rpc. */
|
|---|
| 792 | /* We must check the call-id matches the outstanding callid. */
|
|---|
| 793 | if(pipe_init_outgoing_data(p)) {
|
|---|
| 794 | /* Send a cancel_ack PDU reply. */
|
|---|
| 795 | /* We should probably check the auth-verifier here. */
|
|---|
| 796 | reply = setup_cancel_ack_reply(p, &rpc_in);
|
|---|
| 797 | }
|
|---|
| 798 | break;
|
|---|
| 799 | #endif
|
|---|
| 800 |
|
|---|
| 801 | case RPC_ORPHANED:
|
|---|
| 802 | /* We should probably check the auth-verifier here.
|
|---|
| 803 | For now just free all client data and continue processing. */
|
|---|
| 804 | DEBUG(3,("process_complete_pdu: RPC_ORPHANED. Abandoning rpc call.\n"));
|
|---|
| 805 | reply = True;
|
|---|
| 806 | break;
|
|---|
| 807 |
|
|---|
| 808 | default:
|
|---|
| 809 | DEBUG(0,("process_complete_pdu: Unknown rpc type = %u received.\n", (unsigned int)p->hdr.pkt_type ));
|
|---|
| 810 | break;
|
|---|
| 811 | }
|
|---|
| 812 |
|
|---|
| 813 | /* Reset to little endian. Probably don't need this but it won't hurt. */
|
|---|
| 814 | prs_set_endian_data( &p->in_data.data, RPC_LITTLE_ENDIAN);
|
|---|
| 815 |
|
|---|
| 816 | if (!reply) {
|
|---|
| 817 | DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on pipe %s\n", p->pipe_srv_name));
|
|---|
| 818 | set_incoming_fault(p);
|
|---|
| 819 | setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
|
|---|
| 820 | prs_mem_free(&rpc_in);
|
|---|
| 821 | } else {
|
|---|
| 822 | /*
|
|---|
| 823 | * Reset the lengths. We're ready for a new pdu.
|
|---|
| 824 | */
|
|---|
| 825 | p->in_data.pdu_needed_len = 0;
|
|---|
| 826 | p->in_data.pdu_received_len = 0;
|
|---|
| 827 | }
|
|---|
| 828 |
|
|---|
| 829 | prs_mem_free(&rpc_in);
|
|---|
| 830 | }
|
|---|
| 831 |
|
|---|
| 832 | /****************************************************************************
|
|---|
| 833 | Accepts incoming data on an rpc pipe. Processes the data in pdu sized units.
|
|---|
| 834 | ****************************************************************************/
|
|---|
| 835 |
|
|---|
| 836 | static ssize_t process_incoming_data(pipes_struct *p, char *data, size_t n)
|
|---|
| 837 | {
|
|---|
| 838 | size_t data_to_copy = MIN(n, RPC_MAX_PDU_FRAG_LEN - p->in_data.pdu_received_len);
|
|---|
| 839 |
|
|---|
| 840 | DEBUG(10,("process_incoming_data: Start: pdu_received_len = %u, pdu_needed_len = %u, incoming data = %u\n",
|
|---|
| 841 | (unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len,
|
|---|
| 842 | (unsigned int)n ));
|
|---|
| 843 |
|
|---|
| 844 | if(data_to_copy == 0) {
|
|---|
| 845 | /*
|
|---|
| 846 | * This is an error - data is being received and there is no
|
|---|
| 847 | * space in the PDU. Free the received data and go into the fault state.
|
|---|
| 848 | */
|
|---|
| 849 | DEBUG(0,("process_incoming_data: No space in incoming pdu buffer. Current size = %u \
|
|---|
| 850 | incoming data size = %u\n", (unsigned int)p->in_data.pdu_received_len, (unsigned int)n ));
|
|---|
| 851 | set_incoming_fault(p);
|
|---|
| 852 | return -1;
|
|---|
| 853 | }
|
|---|
| 854 |
|
|---|
| 855 | /*
|
|---|
| 856 | * If we have no data already, wait until we get at least a RPC_HEADER_LEN
|
|---|
| 857 | * number of bytes before we can do anything.
|
|---|
| 858 | */
|
|---|
| 859 |
|
|---|
| 860 | if((p->in_data.pdu_needed_len == 0) && (p->in_data.pdu_received_len < RPC_HEADER_LEN)) {
|
|---|
| 861 | /*
|
|---|
| 862 | * Always return here. If we have more data then the RPC_HEADER
|
|---|
| 863 | * will be processed the next time around the loop.
|
|---|
| 864 | */
|
|---|
| 865 | return fill_rpc_header(p, data, data_to_copy);
|
|---|
| 866 | }
|
|---|
| 867 |
|
|---|
| 868 | /*
|
|---|
| 869 | * At this point we know we have at least an RPC_HEADER_LEN amount of data
|
|---|
| 870 | * stored in current_in_pdu.
|
|---|
| 871 | */
|
|---|
| 872 |
|
|---|
| 873 | /*
|
|---|
| 874 | * If pdu_needed_len is zero this is a new pdu.
|
|---|
| 875 | * Unmarshall the header so we know how much more
|
|---|
| 876 | * data we need, then loop again.
|
|---|
| 877 | */
|
|---|
| 878 |
|
|---|
| 879 | if(p->in_data.pdu_needed_len == 0) {
|
|---|
| 880 | ssize_t rret = unmarshall_rpc_header(p);
|
|---|
| 881 | if (rret == -1 || p->in_data.pdu_needed_len > 0) {
|
|---|
| 882 | return rret;
|
|---|
| 883 | }
|
|---|
| 884 | /* If rret == 0 and pdu_needed_len == 0 here we have a PDU that consists
|
|---|
| 885 | of an RPC_HEADER only. This is a RPC_SHUTDOWN, RPC_CO_CANCEL or RPC_ORPHANED
|
|---|
| 886 | pdu type. Deal with this in process_complete_pdu(). */
|
|---|
| 887 | }
|
|---|
| 888 |
|
|---|
| 889 | /*
|
|---|
| 890 | * Ok - at this point we have a valid RPC_HEADER in p->hdr.
|
|---|
| 891 | * Keep reading until we have a full pdu.
|
|---|
| 892 | */
|
|---|
| 893 |
|
|---|
| 894 | data_to_copy = MIN(data_to_copy, p->in_data.pdu_needed_len);
|
|---|
| 895 |
|
|---|
| 896 | /*
|
|---|
| 897 | * Copy as much of the data as we need into the current_in_pdu buffer.
|
|---|
| 898 | * pdu_needed_len becomes zero when we have a complete pdu.
|
|---|
| 899 | */
|
|---|
| 900 |
|
|---|
| 901 | memcpy( (char *)&p->in_data.current_in_pdu[p->in_data.pdu_received_len], data, data_to_copy);
|
|---|
| 902 | p->in_data.pdu_received_len += data_to_copy;
|
|---|
| 903 | p->in_data.pdu_needed_len -= data_to_copy;
|
|---|
| 904 |
|
|---|
| 905 | /*
|
|---|
| 906 | * Do we have a complete PDU ?
|
|---|
| 907 | * (return the number of bytes handled in the call)
|
|---|
| 908 | */
|
|---|
| 909 |
|
|---|
| 910 | if(p->in_data.pdu_needed_len == 0) {
|
|---|
| 911 | process_complete_pdu(p);
|
|---|
| 912 | return data_to_copy;
|
|---|
| 913 | }
|
|---|
| 914 |
|
|---|
| 915 | DEBUG(10,("process_incoming_data: not a complete PDU yet. pdu_received_len = %u, pdu_needed_len = %u\n",
|
|---|
| 916 | (unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len ));
|
|---|
| 917 |
|
|---|
| 918 | return (ssize_t)data_to_copy;
|
|---|
| 919 | }
|
|---|
| 920 |
|
|---|
| 921 | /****************************************************************************
|
|---|
| 922 | Accepts incoming data on an rpc pipe.
|
|---|
| 923 | ****************************************************************************/
|
|---|
| 924 |
|
|---|
| 925 | ssize_t write_to_pipe(smb_np_struct *p, char *data, size_t n)
|
|---|
| 926 | {
|
|---|
| 927 | DEBUG(6,("write_to_pipe: %x", p->pnum));
|
|---|
| 928 |
|
|---|
| 929 | DEBUG(6,(" name: %s open: %s len: %d\n",
|
|---|
| 930 | p->name, BOOLSTR(p->open), (int)n));
|
|---|
| 931 |
|
|---|
| 932 | dump_data(50, (uint8 *)data, n);
|
|---|
| 933 |
|
|---|
| 934 | return p->namedpipe_write(p->np_state, data, n);
|
|---|
| 935 | }
|
|---|
| 936 |
|
|---|
| 937 | /****************************************************************************
|
|---|
| 938 | Accepts incoming data on an internal rpc pipe.
|
|---|
| 939 | ****************************************************************************/
|
|---|
| 940 |
|
|---|
| 941 | static ssize_t write_to_internal_pipe(void *np_conn, char *data, size_t n)
|
|---|
| 942 | {
|
|---|
| 943 | pipes_struct *p = (pipes_struct*)np_conn;
|
|---|
| 944 | size_t data_left = n;
|
|---|
| 945 |
|
|---|
| 946 | while(data_left) {
|
|---|
| 947 | ssize_t data_used;
|
|---|
| 948 |
|
|---|
| 949 | DEBUG(10,("write_to_pipe: data_left = %u\n", (unsigned int)data_left ));
|
|---|
| 950 |
|
|---|
| 951 | data_used = process_incoming_data(p, data, data_left);
|
|---|
| 952 |
|
|---|
| 953 | DEBUG(10,("write_to_pipe: data_used = %d\n", (int)data_used ));
|
|---|
| 954 |
|
|---|
| 955 | if(data_used < 0) {
|
|---|
| 956 | return -1;
|
|---|
| 957 | }
|
|---|
| 958 |
|
|---|
| 959 | data_left -= data_used;
|
|---|
| 960 | data += data_used;
|
|---|
| 961 | }
|
|---|
| 962 |
|
|---|
| 963 | return n;
|
|---|
| 964 | }
|
|---|
| 965 |
|
|---|
| 966 | /****************************************************************************
|
|---|
| 967 | Replies to a request to read data from a pipe.
|
|---|
| 968 |
|
|---|
| 969 | Headers are interspersed with the data at PDU intervals. By the time
|
|---|
| 970 | this function is called, the start of the data could possibly have been
|
|---|
| 971 | read by an SMBtrans (file_offset != 0).
|
|---|
| 972 |
|
|---|
| 973 | Calling create_rpc_reply() here is a hack. The data should already
|
|---|
| 974 | have been prepared into arrays of headers + data stream sections.
|
|---|
| 975 | ****************************************************************************/
|
|---|
| 976 |
|
|---|
| 977 | ssize_t read_from_pipe(smb_np_struct *p, char *data, size_t n,
|
|---|
| 978 | bool *is_data_outstanding)
|
|---|
| 979 | {
|
|---|
| 980 | if (!p || !p->open) {
|
|---|
| 981 | DEBUG(0,("read_from_pipe: pipe not open\n"));
|
|---|
| 982 | return -1;
|
|---|
| 983 | }
|
|---|
| 984 |
|
|---|
| 985 | DEBUG(6,("read_from_pipe: %x", p->pnum));
|
|---|
| 986 |
|
|---|
| 987 | return p->namedpipe_read(p->np_state, data, n, is_data_outstanding);
|
|---|
| 988 | }
|
|---|
| 989 |
|
|---|
| 990 | /****************************************************************************
|
|---|
| 991 | Replies to a request to read data from a pipe.
|
|---|
| 992 |
|
|---|
| 993 | Headers are interspersed with the data at PDU intervals. By the time
|
|---|
| 994 | this function is called, the start of the data could possibly have been
|
|---|
| 995 | read by an SMBtrans (file_offset != 0).
|
|---|
| 996 |
|
|---|
| 997 | Calling create_rpc_reply() here is a hack. The data should already
|
|---|
| 998 | have been prepared into arrays of headers + data stream sections.
|
|---|
| 999 | ****************************************************************************/
|
|---|
| 1000 |
|
|---|
| 1001 | static ssize_t read_from_internal_pipe(void *np_conn, char *data, size_t n,
|
|---|
| 1002 | bool *is_data_outstanding)
|
|---|
| 1003 | {
|
|---|
| 1004 | pipes_struct *p = (pipes_struct*)np_conn;
|
|---|
| 1005 | uint32 pdu_remaining = 0;
|
|---|
| 1006 | ssize_t data_returned = 0;
|
|---|
| 1007 |
|
|---|
| 1008 | if (!p) {
|
|---|
| 1009 | DEBUG(0,("read_from_pipe: pipe not open\n"));
|
|---|
| 1010 | return -1;
|
|---|
| 1011 | }
|
|---|
| 1012 |
|
|---|
| 1013 | DEBUG(6,(" name: %s len: %u\n", p->name, (unsigned int)n));
|
|---|
| 1014 |
|
|---|
| 1015 | /*
|
|---|
| 1016 | * We cannot return more than one PDU length per
|
|---|
| 1017 | * read request.
|
|---|
| 1018 | */
|
|---|
| 1019 |
|
|---|
| 1020 | /*
|
|---|
| 1021 | * This condition should result in the connection being closed.
|
|---|
| 1022 | * Netapp filers seem to set it to 0xffff which results in domain
|
|---|
| 1023 | * authentications failing. Just ignore it so things work.
|
|---|
| 1024 | */
|
|---|
| 1025 |
|
|---|
| 1026 | if(n > RPC_MAX_PDU_FRAG_LEN) {
|
|---|
| 1027 | DEBUG(5,("read_from_pipe: too large read (%u) requested on \
|
|---|
| 1028 | pipe %s. We can only service %d sized reads.\n", (unsigned int)n, p->name, RPC_MAX_PDU_FRAG_LEN ));
|
|---|
| 1029 | n = RPC_MAX_PDU_FRAG_LEN;
|
|---|
| 1030 | }
|
|---|
| 1031 |
|
|---|
| 1032 | /*
|
|---|
| 1033 | * Determine if there is still data to send in the
|
|---|
| 1034 | * pipe PDU buffer. Always send this first. Never
|
|---|
| 1035 | * send more than is left in the current PDU. The
|
|---|
| 1036 | * client should send a new read request for a new
|
|---|
| 1037 | * PDU.
|
|---|
| 1038 | */
|
|---|
| 1039 |
|
|---|
| 1040 | if((pdu_remaining = p->out_data.current_pdu_len - p->out_data.current_pdu_sent) > 0) {
|
|---|
| 1041 | data_returned = (ssize_t)MIN(n, pdu_remaining);
|
|---|
| 1042 |
|
|---|
| 1043 | DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, current_pdu_sent = %u \
|
|---|
| 1044 | returning %d bytes.\n", p->name, (unsigned int)p->out_data.current_pdu_len,
|
|---|
| 1045 | (unsigned int)p->out_data.current_pdu_sent, (int)data_returned));
|
|---|
| 1046 |
|
|---|
| 1047 | memcpy( data, &p->out_data.current_pdu[p->out_data.current_pdu_sent], (size_t)data_returned);
|
|---|
| 1048 | p->out_data.current_pdu_sent += (uint32)data_returned;
|
|---|
| 1049 | goto out;
|
|---|
| 1050 | }
|
|---|
| 1051 |
|
|---|
| 1052 | /*
|
|---|
| 1053 | * At this point p->current_pdu_len == p->current_pdu_sent (which
|
|---|
| 1054 | * may of course be zero if this is the first return fragment.
|
|---|
| 1055 | */
|
|---|
| 1056 |
|
|---|
| 1057 | DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length \
|
|---|
| 1058 | = %u, prs_offset(&p->out_data.rdata) = %u.\n",
|
|---|
| 1059 | p->name, (int)p->fault_state, (unsigned int)p->out_data.data_sent_length, (unsigned int)prs_offset(&p->out_data.rdata) ));
|
|---|
| 1060 |
|
|---|
| 1061 | if(p->out_data.data_sent_length >= prs_offset(&p->out_data.rdata)) {
|
|---|
| 1062 | /*
|
|---|
| 1063 | * We have sent all possible data, return 0.
|
|---|
| 1064 | */
|
|---|
| 1065 | data_returned = 0;
|
|---|
| 1066 | goto out;
|
|---|
| 1067 | }
|
|---|
| 1068 |
|
|---|
| 1069 | /*
|
|---|
| 1070 | * We need to create a new PDU from the data left in p->rdata.
|
|---|
| 1071 | * Create the header/data/footers. This also sets up the fields
|
|---|
| 1072 | * p->current_pdu_len, p->current_pdu_sent, p->data_sent_length
|
|---|
| 1073 | * and stores the outgoing PDU in p->current_pdu.
|
|---|
| 1074 | */
|
|---|
| 1075 |
|
|---|
| 1076 | if(!create_next_pdu(p)) {
|
|---|
| 1077 | DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n", p->name));
|
|---|
| 1078 | return -1;
|
|---|
| 1079 | }
|
|---|
| 1080 |
|
|---|
| 1081 | data_returned = MIN(n, p->out_data.current_pdu_len);
|
|---|
| 1082 |
|
|---|
| 1083 | memcpy( data, p->out_data.current_pdu, (size_t)data_returned);
|
|---|
| 1084 | p->out_data.current_pdu_sent += (uint32)data_returned;
|
|---|
| 1085 |
|
|---|
| 1086 | out:
|
|---|
| 1087 |
|
|---|
| 1088 | (*is_data_outstanding) = p->out_data.current_pdu_len > n;
|
|---|
| 1089 | return data_returned;
|
|---|
| 1090 | }
|
|---|
| 1091 |
|
|---|
| 1092 | /****************************************************************************
|
|---|
| 1093 | Wait device state on a pipe. Exactly what this is for is unknown...
|
|---|
| 1094 | ****************************************************************************/
|
|---|
| 1095 |
|
|---|
| 1096 | bool wait_rpc_pipe_hnd_state(smb_np_struct *p, uint16 priority)
|
|---|
| 1097 | {
|
|---|
| 1098 | if (p == NULL) {
|
|---|
| 1099 | return False;
|
|---|
| 1100 | }
|
|---|
| 1101 |
|
|---|
| 1102 | if (p->open) {
|
|---|
| 1103 | DEBUG(3,("wait_rpc_pipe_hnd_state: Setting pipe wait state priority=%x on pipe (name=%s)\n",
|
|---|
| 1104 | priority, p->name));
|
|---|
| 1105 |
|
|---|
| 1106 | p->priority = priority;
|
|---|
| 1107 |
|
|---|
| 1108 | return True;
|
|---|
| 1109 | }
|
|---|
| 1110 |
|
|---|
| 1111 | DEBUG(3,("wait_rpc_pipe_hnd_state: Error setting pipe wait state priority=%x (name=%s)\n",
|
|---|
| 1112 | priority, p->name));
|
|---|
| 1113 | return False;
|
|---|
| 1114 | }
|
|---|
| 1115 |
|
|---|
| 1116 |
|
|---|
| 1117 | /****************************************************************************
|
|---|
| 1118 | Set device state on a pipe. Exactly what this is for is unknown...
|
|---|
| 1119 | ****************************************************************************/
|
|---|
| 1120 |
|
|---|
| 1121 | bool set_rpc_pipe_hnd_state(smb_np_struct *p, uint16 device_state)
|
|---|
| 1122 | {
|
|---|
| 1123 | if (p == NULL) {
|
|---|
| 1124 | return False;
|
|---|
| 1125 | }
|
|---|
| 1126 |
|
|---|
| 1127 | if (p->open) {
|
|---|
| 1128 | DEBUG(3,("set_rpc_pipe_hnd_state: Setting pipe device state=%x on pipe (name=%s)\n",
|
|---|
| 1129 | device_state, p->name));
|
|---|
| 1130 |
|
|---|
| 1131 | p->device_state = device_state;
|
|---|
| 1132 |
|
|---|
| 1133 | return True;
|
|---|
| 1134 | }
|
|---|
| 1135 |
|
|---|
| 1136 | DEBUG(3,("set_rpc_pipe_hnd_state: Error setting pipe device state=%x (name=%s)\n",
|
|---|
| 1137 | device_state, p->name));
|
|---|
| 1138 | return False;
|
|---|
| 1139 | }
|
|---|
| 1140 |
|
|---|
| 1141 |
|
|---|
| 1142 | /****************************************************************************
|
|---|
| 1143 | Close an rpc pipe.
|
|---|
| 1144 | ****************************************************************************/
|
|---|
| 1145 |
|
|---|
| 1146 | bool close_rpc_pipe_hnd(smb_np_struct *p)
|
|---|
| 1147 | {
|
|---|
| 1148 | if (!p) {
|
|---|
| 1149 | DEBUG(0,("Invalid pipe in close_rpc_pipe_hnd\n"));
|
|---|
| 1150 | return False;
|
|---|
| 1151 | }
|
|---|
| 1152 |
|
|---|
| 1153 | p->namedpipe_close(p->np_state);
|
|---|
| 1154 |
|
|---|
| 1155 | bitmap_clear(bmap, p->pnum - pipe_handle_offset);
|
|---|
| 1156 |
|
|---|
| 1157 | pipes_open--;
|
|---|
| 1158 |
|
|---|
| 1159 | DEBUG(4,("closed pipe name %s pnum=%x (pipes_open=%d)\n",
|
|---|
| 1160 | p->name, p->pnum, pipes_open));
|
|---|
| 1161 |
|
|---|
| 1162 | DLIST_REMOVE(Pipes, p);
|
|---|
| 1163 |
|
|---|
| 1164 | /* TODO: Remove from pipe open db */
|
|---|
| 1165 |
|
|---|
| 1166 | if ( !delete_pipe_opendb( p ) ) {
|
|---|
| 1167 | DEBUG(3,("close_rpc_pipe_hnd: failed to delete %s "
|
|---|
| 1168 | "pipe from open db.\n", p->name));
|
|---|
| 1169 | }
|
|---|
| 1170 |
|
|---|
| 1171 | TALLOC_FREE(p);
|
|---|
| 1172 |
|
|---|
| 1173 | return True;
|
|---|
| 1174 | }
|
|---|
| 1175 |
|
|---|
| 1176 | /****************************************************************************
|
|---|
| 1177 | Close all pipes on a connection.
|
|---|
| 1178 | ****************************************************************************/
|
|---|
| 1179 |
|
|---|
| 1180 | void pipe_close_conn(connection_struct *conn)
|
|---|
| 1181 | {
|
|---|
| 1182 | smb_np_struct *p, *next;
|
|---|
| 1183 |
|
|---|
| 1184 | for (p=Pipes;p;p=next) {
|
|---|
| 1185 | next = p->next;
|
|---|
| 1186 | if (p->conn == conn) {
|
|---|
| 1187 | close_rpc_pipe_hnd(p);
|
|---|
| 1188 | }
|
|---|
| 1189 | }
|
|---|
| 1190 | }
|
|---|
| 1191 |
|
|---|
| 1192 | /****************************************************************************
|
|---|
| 1193 | Close an rpc pipe.
|
|---|
| 1194 | ****************************************************************************/
|
|---|
| 1195 |
|
|---|
| 1196 | static bool close_internal_rpc_pipe_hnd(void *np_conn)
|
|---|
| 1197 | {
|
|---|
| 1198 | pipes_struct *p = (pipes_struct *)np_conn;
|
|---|
| 1199 | if (!p) {
|
|---|
| 1200 | DEBUG(0,("Invalid pipe in close_internal_rpc_pipe_hnd\n"));
|
|---|
| 1201 | return False;
|
|---|
| 1202 | }
|
|---|
| 1203 |
|
|---|
| 1204 | prs_mem_free(&p->out_data.rdata);
|
|---|
| 1205 | prs_mem_free(&p->in_data.data);
|
|---|
| 1206 |
|
|---|
| 1207 | if (p->auth.auth_data_free_func) {
|
|---|
| 1208 | (*p->auth.auth_data_free_func)(&p->auth);
|
|---|
| 1209 | }
|
|---|
| 1210 |
|
|---|
| 1211 | if (p->mem_ctx) {
|
|---|
| 1212 | talloc_destroy(p->mem_ctx);
|
|---|
| 1213 | }
|
|---|
| 1214 |
|
|---|
| 1215 | if (p->pipe_state_mem_ctx) {
|
|---|
| 1216 | talloc_destroy(p->pipe_state_mem_ctx);
|
|---|
| 1217 | }
|
|---|
| 1218 |
|
|---|
| 1219 | free_pipe_rpc_context( p->contexts );
|
|---|
| 1220 |
|
|---|
| 1221 | /* Free the handles database. */
|
|---|
| 1222 | close_policy_by_pipe(p);
|
|---|
| 1223 |
|
|---|
| 1224 | TALLOC_FREE(p->pipe_user.nt_user_token);
|
|---|
| 1225 | data_blob_free(&p->session_key);
|
|---|
| 1226 | SAFE_FREE(p->pipe_user.ut.groups);
|
|---|
| 1227 |
|
|---|
| 1228 | DLIST_REMOVE(InternalPipes, p);
|
|---|
| 1229 |
|
|---|
| 1230 | ZERO_STRUCTP(p);
|
|---|
| 1231 |
|
|---|
| 1232 | SAFE_FREE(p);
|
|---|
| 1233 |
|
|---|
| 1234 | return True;
|
|---|
| 1235 | }
|
|---|
| 1236 |
|
|---|
| 1237 | /****************************************************************************
|
|---|
| 1238 | Find an rpc pipe given a pipe handle in a buffer and an offset.
|
|---|
| 1239 | ****************************************************************************/
|
|---|
| 1240 |
|
|---|
| 1241 | smb_np_struct *get_rpc_pipe_p(uint16 pnum)
|
|---|
| 1242 | {
|
|---|
| 1243 | if (chain_p) {
|
|---|
| 1244 | return chain_p;
|
|---|
| 1245 | }
|
|---|
| 1246 |
|
|---|
| 1247 | return get_rpc_pipe(pnum);
|
|---|
| 1248 | }
|
|---|
| 1249 |
|
|---|
| 1250 | /****************************************************************************
|
|---|
| 1251 | Find an rpc pipe given a pipe handle.
|
|---|
| 1252 | ****************************************************************************/
|
|---|
| 1253 |
|
|---|
| 1254 | smb_np_struct *get_rpc_pipe(int pnum)
|
|---|
| 1255 | {
|
|---|
| 1256 | smb_np_struct *p;
|
|---|
| 1257 |
|
|---|
| 1258 | DEBUG(4,("search for pipe pnum=%x\n", pnum));
|
|---|
| 1259 |
|
|---|
| 1260 | for (p=Pipes;p;p=p->next) {
|
|---|
| 1261 | DEBUG(5,("pipe name %s pnum=%x (pipes_open=%d)\n",
|
|---|
| 1262 | p->name, p->pnum, pipes_open));
|
|---|
| 1263 | }
|
|---|
| 1264 |
|
|---|
| 1265 | for (p=Pipes;p;p=p->next) {
|
|---|
| 1266 | if (p->pnum == pnum) {
|
|---|
| 1267 | chain_p = p;
|
|---|
| 1268 | return p;
|
|---|
| 1269 | }
|
|---|
| 1270 | }
|
|---|
| 1271 |
|
|---|
| 1272 | return NULL;
|
|---|
| 1273 | }
|
|---|