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;
33 extern struct pipe_id_info pipe_names[];
35 /********************************************************************
37 ********************************************************************/
39 uint32 get_rpc_call_id(void)
41 static uint32 call_id = 1;
45 /*******************************************************************
46 uses SMBreadX to get rest of rpc data
47 ********************************************************************/
49 static BOOL rpc_read(struct cli_state *cli, uint16 fnum,
50 prs_struct *rdata, uint32 data_to_read,
54 int file_offset = rdata_offset;
56 char *data = rdata->data->data;
58 uint32 new_data_size = rdata->data->data_used + data_to_read;
62 file_offset -= rdata_offset;
64 DEBUG(5,("rpc_read: data_to_read: %d data offset: %d file offset: %d\n",
65 data_to_read, rdata_offset, file_offset));
67 if (new_data_size > rdata->data->data_size)
69 mem_grow_data(&rdata->data, True, new_data_size, True);
70 DEBUG(5,("rpc_read: grow buffer to %d\n", rdata->data->data_used));
73 do /* read data using SMBreadX */
75 if (size > data_to_read)
78 new_data_size = rdata->data->data_used + size;
80 if (new_data_size > rdata->data->data_size)
82 mem_grow_data(&rdata->data, True, new_data_size, True);
83 DEBUG(5,("rpc_read: grow buffer to %d\n", rdata->data->data_used));
86 num_read = cli_read(cli, fnum, data, file_offset + 0x100000, size);
88 DEBUG(5,("rpc_read: read offset: %d read: %d to read: %d\n",
89 file_offset, num_read, data_to_read));
91 data_to_read -= num_read;
92 file_offset += num_read;
95 if (cli_error(cli, NULL, &err))
98 } while (num_read > 0 && data_to_read > 0);
99 /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */
101 mem_realloc_data(rdata->data, file_offset + rdata_offset);
102 rdata->data->offset.end = file_offset + rdata_offset;
104 DEBUG(5,("rpc_read: data supposedly left to read:0x%x\n", data_to_read));
106 return data_to_read == 0;
109 /****************************************************************************
111 ****************************************************************************/
112 static BOOL rpc_check_hdr(prs_struct *rdata, uint8 *pkt_type,
113 BOOL *first, BOOL *last, int *len)
117 DEBUG(5,("rpc_check_hdr: rdata->data->data_used: %d\n", rdata->data->data_used));
119 smb_io_rpc_hdr ("rpc_hdr ", &rhdr , rdata, 0);
121 if (!rdata->offset || rdata->offset != 0x10)
123 DEBUG(5,("cli_pipe: error in rpc header\n"));
127 DEBUG(5,("rpc_check_hdr: (after smb_io_rpc_hdr call) rdata->data->data_used: %d\n",
128 rdata->data->data_used));
130 (*first ) = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_FIRST);
131 (*last ) = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_LAST );
132 (*len ) = rhdr.frag_len - rdata->data->data_used;
133 (*pkt_type) = rhdr.pkt_type;
138 /****************************************************************************
139 send data on an rpc pipe, which *must* be in one fragment.
140 receive response data from an rpc pipe, which may be large...
142 read the first fragment: unfortunately have to use SMBtrans for the first
143 bit, then SMBreadX for subsequent bits.
145 if first fragment received also wasn't the last fragment, continue
146 getting fragments until we _do_ receive the last fragment.
148 [note: from a data abstraction viewpoint, this function is marginally
149 complicated by the return side of cli_api_pipe getting in the way
150 (i.e, the SMB header stuff). the proper way to do this is to split
151 cli_api_pipe down into receive / transmit. oh, and split cli_readx
152 down. in other words, state-based (kernel) techniques...]
154 ****************************************************************************/
156 BOOL rpc_api_pipe(struct cli_state *cli, uint16 cmd, uint16 fnum,
157 prs_struct *param , prs_struct *data,
158 prs_struct *rparam, prs_struct *rdata)
162 uint16 setup[2]; /* only need 2 uint16 setup parameters */
164 uint8 pkt_type = 0xff;
168 /* prepare return data and params */
170 /* create setup parameters. */
172 setup[1] = fnum; /* pipe file handle. got this from an SMBcreateX. */
174 /* send the data: receive a response. */
175 if (!cli_api_pipe(cli, "\\PIPE\\\0\0\0", 8,
176 param != NULL ? param->data->data_used : 0,
177 data != NULL ? data ->data->data_used : 0,
180 data != NULL ? 1024 : 0 ,
181 param != NULL ? param->data->data : NULL,
182 data != NULL ? data ->data->data : NULL,
184 rparam != NULL ? rparam->data : NULL,
185 rdata != NULL ? rdata ->data : NULL))
187 DEBUG(5, ("cli_pipe: return critical error\n"));
191 if (cli_error(cli, NULL, &err))
194 if (rdata->data->data == NULL)
197 /**** parse the header: check it's a response record */
199 rdata->data->offset.start = 0;
200 rdata->data->offset.end = rdata->data->data_used;
203 if (!rpc_check_hdr(rdata, &pkt_type, &first, &last, &len))
206 if (pkt_type == RPC_RESPONSE)
208 RPC_HDR_RESP rhdr_resp;
209 smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, rdata, 0);
212 DEBUG(5,("rpc_api_pipe: len left: %d smbtrans read: %d\n",
213 len, rdata->data->data_used));
215 /* check if data to be sent back was too large for one SMB. */
216 /* err status is only informational: the _real_ check is on the length */
217 if (len > 0) /* || err == (0x80000000 | STATUS_BUFFER_OVERFLOW)) */
219 if (!rpc_read(cli, fnum, rdata, len, rdata->data->data_used))
223 /* only one rpc fragment, and it has been read */
226 DEBUG(6,("rpc_api_pipe: fragment first and last both set\n"));
230 while (!last) /* read more fragments until we get the last one */
233 RPC_HDR_RESP rhdr_resp;
237 prs_init(&hps, 0x18, 4, 0, True);
239 num_read = cli_read(cli, fnum, hps.data->data, 0, 0x18);
240 DEBUG(5,("rpc_api_pipe: read header (size:%d)\n", num_read));
242 if (num_read != 0x18)
245 smb_io_rpc_hdr ("rpc_hdr ", &rhdr , &hps, 0);
246 smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, &hps, 0);
250 if (cli_error(cli, NULL, &err))
253 first = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_FIRST);
254 last = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_LAST );
258 DEBUG(4,("rpc_api_pipe: wierd rpc header received\n"));
262 len = rhdr.frag_len - hps.offset;
263 if (!rpc_read(cli, fnum, rdata, len, rdata->data->data_used))
270 /*******************************************************************
271 creates a DCE/RPC bind request
273 - initialises the parse structure.
274 - dynamically allocates the header data structure
275 - caller is expected to free the header data structure once used.
277 ********************************************************************/
279 static BOOL create_rpc_bind_req(prs_struct *rhdr,
281 prs_struct *auth_req,
282 RPC_IFACE *abstract, RPC_IFACE *transfer,
283 char *my_name, char *domain)
287 RPC_AUTH_NTLMSSP_REQ ntlmssp_req;
289 /* create the bind request RPC_HDR_RB */
290 make_rpc_hdr_rb(&hdr_rb, 0x1630, 0x1630, 0x0,
291 0x1, 0x0, 0x1, abstract, transfer);
293 /* stream the bind request data */
294 smb_io_rpc_hdr_rb("", &hdr_rb, rhdr_rb, 0);
295 mem_realloc_data(rhdr_rb->data, rhdr_rb->offset);
297 if (auth_req != NULL)
300 * I have a feeling this is broken right now... JRA.
302 make_rpc_auth_ntlmssp_req(&ntlmssp_req, "NTLMSSP", 0x1,
303 0x0000b2b3, my_name, domain);
304 smb_io_rpc_auth_ntlmssp_req("", &ntlmssp_req, auth_req, 0);
305 mem_realloc_data(auth_req->data, auth_req->offset);
308 /* create the request RPC_HDR */
309 make_rpc_hdr(&hdr, RPC_BIND, 0x0, get_rpc_call_id(),
310 rhdr_rb->offset, auth_req != NULL ? auth_req->offset : 0);
312 smb_io_rpc_hdr("hdr" , &hdr , rhdr, 0);
313 mem_realloc_data(rhdr->data, rhdr->offset);
315 if (rhdr->data == NULL || rhdr_rb->data == NULL)
319 /*** link rpc header, bind acknowledgment and authentication responses ***/
322 rhdr->data->offset.start = 0;
323 rhdr->data->offset.end = rhdr->offset;
324 rhdr->data->next = rhdr_rb->data;
326 if (auth_req != NULL)
328 rhdr_rb->data->offset.start = rhdr->offset;
329 rhdr_rb->data->offset.end = rhdr->offset + rhdr_rb->offset;
330 rhdr_rb->data->next = auth_req->data;
332 auth_req->data->offset.start = rhdr->offset + rhdr_rb->offset;
333 auth_req->data->offset.end = rhdr->offset + auth_req->offset + rhdr_rb->offset;
334 auth_req->data->next = NULL;
338 rhdr_rb->data->offset.start = rhdr->offset;
339 rhdr_rb->data->offset.end = rhdr->offset + rhdr_rb->offset;
340 rhdr_rb->data->next = NULL;
347 /*******************************************************************
348 creates a DCE/RPC bind request
350 - initialises the parse structure.
351 - dynamically allocates the header data structure
352 - caller is expected to free the header data structure once used.
354 ********************************************************************/
356 static BOOL create_rpc_request(prs_struct *rhdr, uint8 op_num, int data_len)
361 DEBUG(5,("create_rpc_request: opnum: 0x%x data_len: 0x%x\n",
364 /* create the rpc header RPC_HDR */
365 make_rpc_hdr(&hdr , RPC_REQUEST, RPC_FLG_FIRST | RPC_FLG_LAST,
366 get_rpc_call_id(), data_len + 0x18, 0);
368 /* create the rpc request RPC_HDR_REQ */
369 make_rpc_hdr_req(&hdr_req, data_len, op_num);
372 smb_io_rpc_hdr ("hdr ", &hdr , rhdr, 0);
373 smb_io_rpc_hdr_req("hdr_req", &hdr_req, rhdr, 0);
375 if (rhdr->data == NULL || rhdr->offset != 0x18)
378 rhdr->data->offset.start = 0;
379 rhdr->data->offset.end = rhdr->offset;
385 /****************************************************************************
386 send a request on an rpc pipe.
387 ****************************************************************************/
388 BOOL rpc_api_pipe_req(struct cli_state *cli, uint16 fnum, uint8 op_num,
389 prs_struct *data, prs_struct *rdata)
391 /* fudge this, at the moment: create the header; memcpy the data. oops. */
397 data_len = data->offset + 0x18;
398 data->data->offset.end = data->offset;
400 prs_init(&hdr , data_len, 4, SAFETY_MARGIN, False);
401 prs_init(&rparam, 0 , 4, 0 , True );
403 create_rpc_request(&hdr, op_num, data_len);
405 mem_realloc_data(hdr.data, data_len);
406 hdr.data->offset.end = data_len;
407 mem_buf_copy(mem_data(&(hdr.data), 0x18), data->data, 0, data->offset);
409 ret = rpc_api_pipe(cli, 0x0026, fnum, NULL, &hdr, &rparam, rdata);
411 prs_mem_free(&rparam);
418 /****************************************************************************
420 ****************************************************************************/
422 BOOL rpc_pipe_set_hnd_state(struct cli_state *cli, char *pipe_name,
423 uint16 fnum, uint16 device_state)
428 BOOL state_set = False;
429 uint16 setup[2]; /* only need 2 uint16 setup parameters */
431 if (pipe_name == NULL)
434 prs_init(¶m , 2, 4, 0 , False);
435 prs_init(&rdata , 0, 4, SAFETY_MARGIN, True );
436 prs_init(&rparam, 0, 4, SAFETY_MARGIN, True );
438 param.data->offset.start = 0;
439 param.data->offset.end = 2;
441 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
442 fnum, pipe_name, device_state));
444 /* create data parameters: device state */
445 SSVAL(param.data->data, 0, device_state);
447 /* create setup parameters. */
449 setup[1] = fnum; /* pipe file handle. got this from an SMBcreateX. */
451 /* send the data on \PIPE\ */
452 if (cli_api_pipe(cli, "\\PIPE\\\0\0\0", 8,
455 param.data->data, NULL, setup,
456 rparam.data, rdata.data))
458 DEBUG(5, ("Set Handle state: return OK\n"));
462 prs_mem_free(¶m );
463 prs_mem_free(&rparam);
464 prs_mem_free(&rdata );
469 /****************************************************************************
470 check the rpc bind acknowledge response
471 ****************************************************************************/
473 static BOOL valid_pipe_name(char *pipe_name, RPC_IFACE *abstract, RPC_IFACE *transfer)
477 while (pipe_names[pipe_idx].client_pipe != NULL)
479 if (strequal(pipe_name, pipe_names[pipe_idx].client_pipe ))
481 DEBUG(5,("Bind Abstract Syntax: "));
482 dump_data(5, (uchar*)&(pipe_names[pipe_idx].abstr_syntax),
483 sizeof(pipe_names[pipe_idx].abstr_syntax));
484 DEBUG(5,("Bind Transfer Syntax: "));
485 dump_data(5, (uchar*)&(pipe_names[pipe_idx].trans_syntax),
486 sizeof(pipe_names[pipe_idx].trans_syntax));
488 /* copy the required syntaxes out so we can do the right bind */
489 memcpy(transfer, &(pipe_names[pipe_idx].trans_syntax),
490 sizeof(pipe_names[pipe_idx].trans_syntax));
491 memcpy(abstract, &(pipe_names[pipe_idx].abstr_syntax),
492 sizeof(pipe_names[pipe_idx].abstr_syntax));
499 DEBUG(5,("Bind RPC Pipe[%s] unsupported\n", pipe_name));
503 /****************************************************************************
504 check the rpc bind acknowledge response
505 ****************************************************************************/
507 static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, char *pipe_name, RPC_IFACE *transfer)
511 while ((pipe_names[i].client_pipe != NULL))
513 DEBUG(6,("bind_rpc_pipe: searching pipe name: client:%s server:%s\n",
514 pipe_names[i].client_pipe , pipe_names[i].server_pipe ));
516 if ((strequal(pipe_name, pipe_names[i].client_pipe )))
518 if (strequal(hdr_ba->addr.str, pipe_names[i].server_pipe ))
520 DEBUG(5,("bind_rpc_pipe: server pipe_name found: %s\n",
521 pipe_names[i].server_pipe ));
526 DEBUG(2,("bind_rpc_pipe: pipe_name %s != expected pipe %s\n",
527 pipe_names[i].server_pipe , hdr_ba->addr.str));
537 if (pipe_names[i].server_pipe == NULL)
539 DEBUG(2,("bind_rpc_pipe: pipe name %s unsupported\n", hdr_ba->addr.str));
543 /* check the transfer syntax */
544 if (!((hdr_ba->transfer.version == transfer->version) &&
545 (memcmp(hdr_ba->transfer.data, transfer->data,
546 sizeof(transfer->version)) ==0)))
548 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
552 /* lkclXXXX only accept one result: check the result(s) */
553 if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0)
555 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
556 hdr_ba->res.num_results, hdr_ba->res.reason));
559 DEBUG(5,("bind_rpc_pipe: accepted!\n"));
563 /****************************************************************************
565 ****************************************************************************/
567 BOOL rpc_pipe_bind(struct cli_state *cli, char *pipe_name, uint16 fnum,
568 RPC_IFACE *abstract, RPC_IFACE *transfer, BOOL ntlmssp_auth,
569 char *my_name, char *domain)
578 BOOL valid_ack = False;
580 if (pipe_name == NULL || abstract == NULL || transfer == NULL)
583 DEBUG(5,("Bind RPC Pipe[%x]: %s\n", fnum, pipe_name));
585 if (!valid_pipe_name(pipe_name, abstract, transfer))
588 prs_init(&hdr , 0x10 , 4, 0x0 , False);
589 prs_init(&hdr_rb , 1024 , 4, SAFETY_MARGIN, False);
590 prs_init(&auth_req, ntlmssp_auth ? 1024 : 0, 4, SAFETY_MARGIN, False);
592 prs_init(&rdata , 0 , 4, SAFETY_MARGIN, True );
593 prs_init(&rparam, 0 , 4, SAFETY_MARGIN, True );
595 create_rpc_bind_req(&hdr, &hdr_rb, ntlmssp_auth ? &auth_req : NULL,
596 abstract, transfer, my_name, domain);
598 /* this is a hack due to limitations in rpc_api_pipe */
599 prs_init(&data, mem_buf_len(hdr.data), 4, 0x0, False);
600 mem_buf_copy(data.data->data, hdr.data, 0, mem_buf_len(hdr.data));
602 /* send data on \PIPE\. receive a response */
603 if (rpc_api_pipe(cli, 0x0026, fnum, NULL, &data, &rparam, &rdata))
607 DEBUG(5, ("rpc_api_pipe: return OK\n"));
609 smb_io_rpc_hdr_ba("", &hdr_ba, &rdata, 0);
611 if (rdata.offset != 0)
612 valid_ack = check_bind_response(&hdr_ba, pipe_name, transfer);
615 prs_mem_free(&data );
617 prs_mem_free(&hdr_rb );
618 prs_mem_free(&auth_req);
619 prs_mem_free(&rdata );
620 prs_mem_free(&rparam );
625 /****************************************************************************
627 ****************************************************************************/
629 BOOL do_session_open(struct cli_state *cli, char *pipe_name, uint16 *fnum)
634 /******************* open the pipe *****************/
635 if (((*fnum) = cli_open(cli, pipe_name, O_CREAT|O_WRONLY, DENY_NONE)) == 0xffff)
637 DEBUG(1,("do_session_open: cli_open failed\n"));
641 /**************** Set Named Pipe State ***************/
642 if (!rpc_pipe_set_hnd_state(cli, pipe_name, (*fnum), 0x4300))
644 DEBUG(1,("do_session_open: pipe hnd state failed\n"));
648 /******************* bind request on pipe *****************/
649 if (!rpc_pipe_bind(cli, pipe_name, (*fnum), &abstract, &transfer,
652 DEBUG(1,("do_session_open: rpc bind failed\n"));
659 /****************************************************************************
660 open an encrypted session
661 ****************************************************************************/
663 BOOL do_ntlm_session_open(struct cli_state *cli, char *pipe_name, uint16 *fnum,
664 char *my_name, char *domain)
669 /******************* open the pipe *****************/
670 if (((*fnum) = cli_open(cli, pipe_name, O_CREAT|O_WRONLY, DENY_NONE)) == 0xffff)
672 DEBUG(1,("do_ntlm_session_open: cli_open failed\n"));
676 /**************** Set Named Pipe State ***************/
677 if (!rpc_pipe_set_hnd_state(cli, pipe_name, (*fnum), 0x4300))
679 DEBUG(1,("do_ntlm_session_open: pipe hnd state failed\n"));
683 /******************* bind request on pipe *****************/
684 if (!rpc_pipe_bind(cli, pipe_name, (*fnum), &abstract, &transfer,
685 True, my_name, domain))
687 DEBUG(1,("do_ntlm_session_open: rpc bind failed\n"));
694 /****************************************************************************
696 ****************************************************************************/
698 void do_session_close(struct cli_state *cli, uint16 fnum)
702 cli_close(cli, fnum);