3 * Unix SMB/Netbios implementation.
5 * RPC Pipe client / server routines
6 * Copyright (C) Andrew Tridgell 1992-1998,
7 * Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
8 * Copyright (C) Paul Ashton 1998.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 extern int DEBUGLEVEL;
35 extern struct pipe_id_info pipe_names[];
37 /********************************************************************
39 ********************************************************************/
40 uint32 get_rpc_call_id(void)
42 static uint32 call_id = 1;
46 /*******************************************************************
47 uses SMBreadX to get rest of rpc data
48 ********************************************************************/
49 static BOOL rpc_read(struct cli_state *cli, int t_idx, uint16 fnum,
50 prs_struct *rdata, uint32 data_to_read)
52 uint32 data_offset = rdata->data->data_used;
55 char *data = rdata->data->data;
57 data += rdata->data->data_used;
59 if (data_offset + data_to_read > rdata->data->data_size)
61 mem_grow_data(&rdata->data, True, rdata->data->data_used + data_to_read);
62 DEBUG(5,("rpc_read: grow buffer to %d\n", rdata->data->data_used));
65 do /* read data using SMBreadX */
67 if (size > data_to_read) size = data_to_read;
69 if (data_offset + size > rdata->data->data_size)
71 mem_grow_data(&rdata->data, True, rdata->data->data_used + size);
72 DEBUG(5,("rpc_read: grow buffer to %d\n", rdata->data->data_used));
75 num_read = cli_readx(cli, t_idx, fnum, data, data_offset, size);
77 DEBUG(5,("rpc_read: read offset: %d read: %d to read: %d\n",
78 data_offset, num_read, data_to_read));
80 data_to_read -= num_read;
81 data_offset += num_read;
84 if (cli_error(cli, NULL, &err)) return False;
86 } while (num_read > 0 && data_to_read > 0); /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */
88 mem_realloc_data(rdata->data, rdata->data->data_used);
89 rdata->data->offset.end = rdata->data->data_used;
91 DEBUG(5,("rpc_read: data supposedly left to read:0x%x\n", data_to_read));
93 return data_to_read == 0;
96 /****************************************************************************
98 ****************************************************************************/
99 static BOOL rpc_check_hdr(prs_struct *rdata, uint8 *pkt_type,
100 BOOL *first, BOOL *last, uint32 *len)
104 smb_io_rpc_hdr ("rpc_hdr ", &rhdr , rdata, 0);
106 if (!rdata->offset || rdata->offset != 0x10)
108 DEBUG(5,("cli_pipe: error in rpc header\n"));
112 (*first ) = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_FIRST);
113 (*last ) = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_LAST );
114 (*len ) = rhdr.frag_len - rdata->data->data_used;
115 (*pkt_type) = rhdr.pkt_type;
120 /****************************************************************************
121 send data on an rpc pipe, which *must* be in one fragment.
122 receive response data from an rpc pipe, which may be large...
124 read the first fragment: unfortunately have to use SMBtrans for the first
125 bit, then SMBreadX for subsequent bits.
127 if first fragment received also wasn't the last fragment, continue
128 getting fragments until we _do_ receive the last fragment.
130 [note: from a data abstraction viewpoint, this function is marginally
131 complicated by the return side of cli_api_pipe getting in the way
132 (i.e, the SMB header stuff). the proper way to do this is to split
133 cli_api_pipe down into receive / transmit. oh, and split cli_readx
134 down. in other words, state-based (kernel) techniques...]
136 ****************************************************************************/
137 BOOL rpc_api_pipe(struct cli_state *cli, int t_idx,
138 uint16 cmd, uint16 fnum,
139 prs_struct *param , prs_struct *data,
140 prs_struct *rparam, prs_struct *rdata)
144 uint16 setup[2]; /* only need 2 uint16 setup parameters */
146 uint8 pkt_type = 0xff;
150 /* prepare return data and params */
152 /* create setup parameters. */
154 setup[1] = fnum; /* pipe file handle. got this from an SMBcreateX. */
156 /* send the data: receive a response. */
157 if (!cli_api_pipe(cli, t_idx, "\\PIPE\\\0\0\0", 8,
159 param != NULL ? param->data->data_used : 0,
160 data != NULL ? data ->data->data_used : 0,
164 data != NULL ? 1024 : 0 ,
166 param != NULL ? param->data->data : NULL,
167 data != NULL ? data ->data->data : NULL,
170 rparam != NULL ? rparam->data : NULL,
171 rdata != NULL ? rdata ->data : NULL))
173 DEBUG(5, ("cli_pipe: return critical error\n"));
177 if (cli_error(cli, NULL, &err)) return False;
179 if (rdata->data->data == NULL) return False;
181 /**** parse the header: check it's a response record */
183 rdata->data->offset.start = 0;
184 rdata->data->offset.end = rdata->data->data_used;
187 if (!rpc_check_hdr(rdata, &pkt_type, &first, &last, &len)) return False;
189 if (pkt_type == RPC_RESPONSE)
192 smb_io_rpc_hdr_rr("rpc_hdr_rr", &rhdr_rr, rdata, 0);
197 DEBUG(6,("rpc_api_pipe: fragment first and last both set\n"));
201 /* check if data to be sent back was too large for one SMB. */
202 /* err status is only informational: the _real_ check is on the length */
203 if (len < rdata->data->data_used) /* || err == (0x80000000 | STATUS_BUFFER_OVERFLOW)) */
205 if (!rpc_read(cli, t_idx, fnum, rdata, len)) return False;
208 /* only one rpc fragment, and it has been read */
209 if (first && last) return True;
211 while (!last) /* read more fragments until we get the last one */
218 prs_init(&hps, 0x18, 4, 0, True);
220 num_read = cli_readx(cli, t_idx, fnum, hps.data->data, 0, 0x18);
221 DEBUG(5,("rpc_api_pipe: read header (size:%d)\n", num_read));
223 if (num_read != 0x18) return False;
225 smb_io_rpc_hdr ("rpc_hdr ", &rhdr , &hps, 0);
226 smb_io_rpc_hdr_rr("rpc_hdr_rr", &rhdr_rr, &hps, 0);
230 if (cli_error(cli, NULL, &err)) return False;
232 first = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_FIRST);
233 last = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_LAST );
237 DEBUG(4,("rpc_api_pipe: wierd rpc header received\n"));
241 len = rhdr.frag_len - hps.offset;
242 if (!rpc_read(cli, t_idx, fnum, rdata, len)) return False;
248 /*******************************************************************
249 creates a DCE/RPC bind request
251 - initialises the parse structure.
252 - dynamically allocates the header data structure
253 - caller is expected to free the header data structure once used.
255 ********************************************************************/
256 static BOOL create_rpc_bind_req(prs_struct *rhdr,
258 prs_struct *auth_req,
259 RPC_IFACE *abstract, RPC_IFACE *transfer,
260 char *my_name, char *domain)
264 RPC_AUTH_NTLMSSP_REQ ntlmssp_req;
266 /* create the bind request RPC_HDR_RB */
267 make_rpc_hdr_rb(&hdr_rb,
272 /* stream the bind request data */
273 smb_io_rpc_hdr_rb("", &hdr_rb, rhdr_rb, 0);
274 mem_realloc_data(rhdr_rb->data, rhdr_rb->offset);
276 if (auth_req != NULL)
278 make_rpc_auth_ntlmssp_req(&ntlmssp_req,
282 smb_io_rpc_auth_ntlmssp_req("", &ntlmssp_req, auth_req, 0);
283 mem_realloc_data(auth_req->data, auth_req->offset);
286 /* create the request RPC_HDR */
287 make_rpc_hdr(&hdr, RPC_BIND, 0x0, get_rpc_call_id(),
289 auth_req != NULL ? auth_req->offset : 0);
291 smb_io_rpc_hdr("hdr" , &hdr , rhdr, 0);
292 mem_realloc_data(rhdr->data, rhdr->offset);
294 if (rhdr->data == NULL || rhdr_rb->data == NULL) return False;
297 /*** link rpc header, bind acknowledgment and authentication responses ***/
300 rhdr->data->offset.start = 0;
301 rhdr->data->offset.end = rhdr->offset;
302 rhdr->data->next = rhdr_rb->data;
304 if (auth_req != NULL)
306 rhdr_rb->data->offset.start = rhdr->offset;
307 rhdr_rb->data->offset.end = rhdr->offset + rhdr_rb->offset;
308 rhdr_rb->data->next = auth_req->data;
310 auth_req->data->offset.start = rhdr->offset + rhdr_rb->offset;
311 auth_req->data->offset.end = rhdr->offset + auth_req->offset + rhdr_rb->offset;
312 auth_req->data->next = NULL;
316 rhdr_rb->data->offset.start = rhdr->offset;
317 rhdr_rb->data->offset.end = rhdr->offset + rhdr_rb->offset;
318 rhdr_rb->data->next = NULL;
325 /*******************************************************************
326 creates a DCE/RPC bind request
328 - initialises the parse structure.
329 - dynamically allocates the header data structure
330 - caller is expected to free the header data structure once used.
332 ********************************************************************/
333 static BOOL create_rpc_request(prs_struct *rhdr, uint8 op_num, int data_len)
338 DEBUG(5,("create_rpc_request: opnum: 0x%x data_len: 0x%x\n",
341 /* create the rpc header RPC_HDR */
342 make_rpc_hdr (&hdr , RPC_REQUEST, RPC_FLG_FIRST | RPC_FLG_LAST,
343 get_rpc_call_id(), data_len + 0x18, 0);
345 /* create the rpc request RPC_HDR_RR */
346 make_rpc_hdr_rr(&hdr_rr, data_len, op_num);
349 smb_io_rpc_hdr ("hdr" , &hdr , rhdr, 0);
350 smb_io_rpc_hdr_rr("hdr_rr", &hdr_rr, rhdr, 0);
352 if (rhdr->data == NULL || rhdr->offset != 0x18) return False;
354 rhdr->data->offset.start = 0;
355 rhdr->data->offset.end = rhdr->offset;
361 /****************************************************************************
362 send a request on an rpc pipe.
363 ****************************************************************************/
364 BOOL rpc_api_pipe_req(struct cli_state *cli, int t_idx, uint16 fnum,
366 prs_struct *data, prs_struct *rdata)
368 /* fudge this, at the moment: create the header; memcpy the data. oops. */
374 data_len = data->offset + 0x18;
375 data->data->offset.end = data->offset;
377 prs_init(&hdr , data_len, 4, SAFETY_MARGIN, False);
378 prs_init(&rparam, 0 , 4, 0 , True );
380 create_rpc_request(&hdr, op_num, data_len);
382 mem_realloc_data(hdr.data, data_len);
383 hdr.data->offset.end = data_len;
384 mem_buf_copy(mem_data(&(hdr.data), 0x18), data->data, 0, data->offset);
386 ret = rpc_api_pipe(cli, t_idx, 0x0026, fnum, NULL, &hdr, &rparam, rdata);
388 prs_mem_free(&rparam);
395 /****************************************************************************
397 ****************************************************************************/
398 BOOL rpc_pipe_set_hnd_state(struct cli_state *cli, int t_idx,
399 char *pipe_name, uint16 fnum, uint16 device_state)
404 BOOL state_set = False;
405 uint16 setup[2]; /* only need 2 uint16 setup parameters */
407 if (pipe_name == NULL) return False;
409 prs_init(¶m , 2, 4, 0 , False);
410 prs_init(&rdata , 0, 4, SAFETY_MARGIN, True );
411 prs_init(&rparam, 0, 4, SAFETY_MARGIN, True );
413 param.data->offset.start = 0;
414 param.data->offset.end = 2;
416 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
417 fnum, pipe_name, device_state));
419 /* create data parameters: device state */
420 SSVAL(param.data->data, 0, device_state);
422 /* create setup parameters. */
424 setup[1] = fnum; /* pipe file handle. got this from an SMBcreateX. */
426 /* send the data on \PIPE\ */
427 if (cli_api_pipe(cli, t_idx, "\\PIPE\\\0\0\0", 8,
433 param.data->data, NULL, setup,
435 rparam.data, rdata.data))
437 DEBUG(5, ("Set Handle state: return OK\n"));
441 prs_mem_free(¶m );
442 prs_mem_free(&rparam);
443 prs_mem_free(&rdata );
448 /****************************************************************************
449 check the rpc bind acknowledge response
450 ****************************************************************************/
451 static BOOL valid_pipe_name(char *pipe_name,
452 RPC_IFACE *abstract, RPC_IFACE *transfer)
456 while (pipe_names[pipe_idx].client_pipe != NULL)
458 if (strcmp(pipe_name, pipe_names[pipe_idx].client_pipe ) == 0)
460 DEBUG(5,("Bind Abstract Syntax: "));
461 dump_data(5, (uchar*)&(pipe_names[pipe_idx].abstr_syntax), sizeof(pipe_names[pipe_idx].abstr_syntax));
462 DEBUG(5,("Bind Transfer Syntax: "));
463 dump_data(5, (uchar*)&(pipe_names[pipe_idx].trans_syntax), sizeof(pipe_names[pipe_idx].trans_syntax));
465 /* copy the required syntaxes out so we can do the right bind */
466 memcpy(transfer, &(pipe_names[pipe_idx].trans_syntax), sizeof(pipe_names[pipe_idx].trans_syntax));
467 memcpy(abstract, &(pipe_names[pipe_idx].abstr_syntax), sizeof(pipe_names[pipe_idx].abstr_syntax));
474 DEBUG(5,("Bind RPC Pipe[%s] unsupported\n", pipe_name));
478 /****************************************************************************
479 check the rpc bind acknowledge response
480 ****************************************************************************/
481 static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, char *pipe_name, RPC_IFACE *transfer)
485 while ((pipe_names[i].client_pipe != NULL))
487 DEBUG(6,("bind_rpc_pipe: searching pipe name: client:%s server:%s\n",
488 pipe_names[i].client_pipe , pipe_names[i].server_pipe ));
490 if ((strcmp(pipe_name, pipe_names[i].client_pipe ) == 0))
492 if (strcmp(hdr_ba->addr.str, pipe_names[i].server_pipe ) == 0)
494 DEBUG(5,("bind_rpc_pipe: server pipe_name found: %s\n",
495 pipe_names[i].server_pipe ));
500 DEBUG(2,("bind_rpc_pipe: pipe_name %s != expected pipe %s\n",
501 pipe_names[i].server_pipe , hdr_ba->addr.str));
511 if (pipe_names[i].server_pipe == NULL)
513 DEBUG(2,("bind_rpc_pipe: pipe name %s unsupported\n", hdr_ba->addr.str));
517 /* check the transfer syntax */
518 if (!((hdr_ba->transfer.version == transfer->version) &&
519 (memcmp(hdr_ba->transfer.data, transfer->data,
520 sizeof(transfer->version)) ==0)))
522 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
526 /* lkclXXXX only accept one result: check the result(s) */
527 if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0)
529 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
530 hdr_ba->res.num_results,
531 hdr_ba->res.reason));
534 DEBUG(5,("bind_rpc_pipe: accepted!\n"));
538 /****************************************************************************
540 ****************************************************************************/
541 BOOL rpc_pipe_bind(struct cli_state *cli, int t_idx, char *pipe_name, uint16 fnum,
542 RPC_IFACE *abstract, RPC_IFACE *transfer, BOOL ntlmssp_auth,
543 char *my_name, char *domain)
552 BOOL valid_ack = False;
554 if (pipe_name == NULL || abstract == NULL || transfer == NULL) return False;
556 DEBUG(5,("Bind RPC Pipe[%x]: %s\n", fnum, pipe_name));
558 if (!valid_pipe_name(pipe_name, abstract, transfer)) return False;
560 prs_init(&hdr , 0x10 , 4, 0x0 , False);
561 prs_init(&hdr_rb , 1024 , 4, SAFETY_MARGIN, False);
562 prs_init(&auth_req, ntlmssp_auth ? 1024 : 0, 4, SAFETY_MARGIN, False);
564 prs_init(&rdata , 0 , 4, SAFETY_MARGIN, True );
565 prs_init(&rparam, 0 , 4, SAFETY_MARGIN, True );
567 create_rpc_bind_req(&hdr, &hdr_rb, ntlmssp_auth ? &auth_req : NULL,
571 /* this is a hack due to limitations in rpc_api_pipe */
572 prs_init(&data, mem_buf_len(hdr.data), 4, 0x0, False);
573 mem_buf_copy(data.data->data, hdr.data, 0, mem_buf_len(hdr.data));
575 /* send data on \PIPE\. receive a response */
576 if (rpc_api_pipe(cli, t_idx, 0x0026, fnum, NULL, &data, &rparam, &rdata))
580 DEBUG(5, ("rpc_api_pipe: return OK\n"));
582 smb_io_rpc_hdr_ba("", &hdr_ba, &rdata, 0);
584 if (rdata.offset != 0) valid_ack = check_bind_response(&hdr_ba, pipe_name, transfer);
587 prs_mem_free(&data );
589 prs_mem_free(&hdr_rb );
590 prs_mem_free(&auth_req);
591 prs_mem_free(&rdata );
592 prs_mem_free(&rparam );
597 /****************************************************************************
599 ****************************************************************************/
600 BOOL do_session_open(struct cli_state *cli, int t_idx,
601 char *pipe_name, uint16 *fnum)
607 /******************* open the pipe *****************/
608 if (((*fnum) = cli_open(cli, t_idx, pipe_name, O_CREAT|O_RDONLY, DENY_NONE,
609 NULL, NULL, NULL)) == 0xffff)
611 DEBUG(1,("do_session_open: cli_open failed\n"));
615 /**************** Set Named Pipe State ***************/
616 if (!rpc_pipe_set_hnd_state(cli, t_idx, pipe_name, (*fnum), 0x4300))
618 DEBUG(1,("do_session_open: pipe hnd state failed\n"));
622 /******************* bind request on pipe *****************/
623 if (!rpc_pipe_bind(cli, t_idx, pipe_name, (*fnum),
624 &abstract, &transfer,
627 DEBUG(1,("do_session_open: rpc bind failed\n"));
635 /****************************************************************************
636 open an encrypted session
637 ****************************************************************************/
638 BOOL do_ntlm_session_open(struct cli_state *cli, int t_idx,
639 char *pipe_name, uint16 *fnum,
640 char *my_name, char *domain)
645 /******************* open the pipe *****************/
646 if (((*fnum) = cli_open(cli, t_idx, pipe_name, O_CREAT|O_RDONLY, DENY_NONE,
647 NULL, NULL, NULL)) == 0xffff)
649 DEBUG(1,("do_ntlm_session_open: cli_open failed\n"));
653 /**************** Set Named Pipe State ***************/
654 if (!rpc_pipe_set_hnd_state(cli, t_idx, pipe_name, (*fnum), 0x4300))
656 DEBUG(1,("do_ntlm_session_open: pipe hnd state failed\n"));
660 /******************* bind request on pipe *****************/
661 if (!rpc_pipe_bind(cli, t_idx, pipe_name, (*fnum),
662 &abstract, &transfer,
663 True, my_name, domain))
665 DEBUG(1,("do_ntlm_session_open: rpc bind failed\n"));
673 /****************************************************************************
675 ****************************************************************************/
676 void do_session_close(struct cli_state *cli, int t_idx, uint16 fnum)
680 cli_close(cli, t_idx, fnum, 0);