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[];
34 extern fstring global_myworkgroup;
35 extern pstring global_myname;
37 /********************************************************************
39 ********************************************************************/
41 uint32 get_rpc_call_id(void)
43 static uint32 call_id = 1;
47 /*******************************************************************
48 uses SMBreadX to get rest of rpc data
49 ********************************************************************/
51 static BOOL rpc_read(struct cli_state *cli,
52 prs_struct *rdata, uint32 data_to_read,
56 int file_offset = rdata_offset;
58 char *data = rdata->data->data;
61 uint32 new_data_size = rdata->data->data_used + data_to_read;
65 file_offset -= rdata_offset;
67 DEBUG(5,("rpc_read: data_to_read: %d data offset: %d file offset: %d\n",
68 data_to_read, rdata_offset, file_offset));
70 if (new_data_size > rdata->data->data_size)
72 mem_grow_data(&rdata->data, True, new_data_size, True);
73 DEBUG(5,("rpc_read: grow buffer to %d\n", rdata->data->data_used));
76 do /* read data using SMBreadX */
78 if (size > data_to_read)
81 new_data_size = rdata->data->data_used + size;
83 if (new_data_size > rdata->data->data_size)
85 mem_grow_data(&rdata->data, True, new_data_size, True);
86 DEBUG(5,("rpc_read: grow buffer to %d\n", rdata->data->data_used));
89 num_read = cli_read(cli, cli->nt_pipe_fnum, data, file_offset + 0x100000, size);
91 DEBUG(5,("rpc_read: read offset: %d read: %d to read: %d\n",
92 file_offset, num_read, data_to_read));
94 data_to_read -= num_read;
95 file_offset += num_read;
98 cli_error(cli, (int *)&errclass, (int *)&err);
102 } while (num_read > 0 && data_to_read > 0);
103 /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */
105 mem_realloc_data(rdata->data, file_offset + rdata_offset);
106 rdata->data->offset.end = file_offset + rdata_offset;
108 DEBUG(5,("rpc_read: data supposedly left to read:0x%x\n", data_to_read));
110 return data_to_read == 0;
113 /****************************************************************************
115 ****************************************************************************/
116 static BOOL rpc_check_hdr(prs_struct *rdata, uint8 *pkt_type,
117 BOOL *first, BOOL *last, int *len)
121 DEBUG(5,("rpc_check_hdr: rdata->data->data_used: %d\n", rdata->data->data_used));
123 smb_io_rpc_hdr ("rpc_hdr ", &rhdr , rdata, 0);
125 if (!rdata->offset || rdata->offset != 0x10)
127 DEBUG(0,("cli_pipe: error in rpc header\n"));
131 DEBUG(5,("rpc_check_hdr: (after smb_io_rpc_hdr call) rdata->data->data_used: %d\n",
132 rdata->data->data_used));
134 (*first ) = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_FIRST);
135 (*last ) = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_LAST );
136 (*len ) = rhdr.frag_len - rdata->data->data_used;
137 (*pkt_type) = rhdr.pkt_type;
142 /****************************************************************************
143 send data on an rpc pipe, which *must* be in one fragment.
144 receive response data from an rpc pipe, which may be large...
146 read the first fragment: unfortunately have to use SMBtrans for the first
147 bit, then SMBreadX for subsequent bits.
149 if first fragment received also wasn't the last fragment, continue
150 getting fragments until we _do_ receive the last fragment.
152 [note: from a data abstraction viewpoint, this function is marginally
153 complicated by the return side of cli_api_pipe getting in the way
154 (i.e, the SMB header stuff). the proper way to do this is to split
155 cli_api_pipe down into receive / transmit. oh, and split cli_readx
156 down. in other words, state-based (kernel) techniques...]
158 ****************************************************************************/
160 BOOL rpc_api_pipe(struct cli_state *cli, uint16 cmd,
161 prs_struct *param , prs_struct *data,
162 prs_struct *rparam, prs_struct *rdata)
166 uint16 setup[2]; /* only need 2 uint16 setup parameters */
169 uint8 pkt_type = 0xff;
174 * Setup the pointers from the incoming.
176 char *pparams = param ? param->data->data : NULL;
177 int params_len = param ? param->data->data_used : 0;
178 char *pdata = data ? data->data->data : NULL;
179 int data_len = data ? data->data->data_used : 0;
182 * Setup the pointers to the outgoing.
184 char **pp_ret_params = rparam ? &rparam->data->data : NULL;
185 uint32 *p_ret_params_len = rparam ? &rparam->data->data_used : NULL;
187 char **pp_ret_data = rdata ? &rdata->data->data : NULL;
188 uint32 *p_ret_data_len = rdata ? &rdata->data->data_used : NULL;
190 /* create setup parameters. */
192 setup[1] = cli->nt_pipe_fnum; /* pipe file handle. got this from an SMBOpenX. */
194 /* send the data: receive a response. */
195 if (!cli_api_pipe(cli, "\\PIPE\\\0\0\0", 8,
196 setup, 2, 0, /* Setup, length, max */
197 pparams, params_len, 0, /* Params, length, max */
198 pdata, data_len, 1024, /* data, length, max */
199 pp_ret_params, p_ret_params_len, /* return params, len */
200 pp_ret_data, p_ret_data_len)) /* return data, len */
202 DEBUG(0, ("cli_pipe: return critical error. Error was %s\n", cli_errstr(cli)));
206 if (rdata->data->data == NULL)
209 /**** parse the header: check it's a response record */
211 rdata->data->offset.start = 0;
212 rdata->data->offset.end = rdata->data->data_used;
215 /* cli_api_pipe does an ordinary Realloc - we have no margins now. */
216 rdata->data->margin = 0;
218 rparam->data->margin = 0;
220 if (!rpc_check_hdr(rdata, &pkt_type, &first, &last, &len))
223 if (pkt_type == RPC_RESPONSE)
225 RPC_HDR_RESP rhdr_resp;
226 smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, rdata, 0);
229 DEBUG(5,("rpc_api_pipe: len left: %d smbtrans read: %d\n",
230 len, rdata->data->data_used));
232 /* check if data to be sent back was too large for one SMB. */
233 /* err status is only informational: the _real_ check is on the length */
234 if (len > 0) /* || err == (0x80000000 | STATUS_BUFFER_OVERFLOW)) */
236 if (!rpc_read(cli, rdata, len, rdata->data->data_used))
240 /* only one rpc fragment, and it has been read */
243 DEBUG(6,("rpc_api_pipe: fragment first and last both set\n"));
247 while (!last) /* read more fragments until we get the last one */
250 RPC_HDR_RESP rhdr_resp;
254 prs_init(&hps, 0x18, 4, 0, True);
256 num_read = cli_read(cli, cli->nt_pipe_fnum, hps.data->data, 0, 0x18);
257 DEBUG(5,("rpc_api_pipe: read header (size:%d)\n", num_read));
259 if (num_read != 0x18)
262 smb_io_rpc_hdr ("rpc_hdr ", &rhdr , &hps, 0);
263 smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, &hps, 0);
267 cli_error(cli, (int *)&errclass, (int *)&err);
271 first = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_FIRST);
272 last = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_LAST );
276 DEBUG(0,("rpc_api_pipe: wierd rpc header received\n"));
280 len = rhdr.frag_len - hps.offset;
281 if (!rpc_read(cli, rdata, len, rdata->data->data_used))
288 /*******************************************************************
289 creates a DCE/RPC bind request
291 - initialises the parse structure.
292 - dynamically allocates the header data structure
293 - caller is expected to free the header data structure once used.
295 ********************************************************************/
297 static BOOL create_rpc_bind_req(prs_struct *rhdr,
299 prs_struct *auth_req,
300 RPC_IFACE *abstract, RPC_IFACE *transfer,
301 char *my_name, char *domain)
305 RPC_AUTH_NTLMSSP_REQ ntlmssp_req;
307 /* create the bind request RPC_HDR_RB */
308 make_rpc_hdr_rb(&hdr_rb, 0x1630, 0x1630, 0x0,
309 0x1, 0x0, 0x1, abstract, transfer);
311 /* stream the bind request data */
312 smb_io_rpc_hdr_rb("", &hdr_rb, rhdr_rb, 0);
313 mem_realloc_data(rhdr_rb->data, rhdr_rb->offset);
315 if (auth_req != NULL)
318 * I have a feeling this is broken right now... JRA.
320 make_rpc_auth_ntlmssp_req(&ntlmssp_req, "NTLMSSP", 0x1,
321 0x0000b2b3, my_name, domain);
322 smb_io_rpc_auth_ntlmssp_req("", &ntlmssp_req, auth_req, 0);
323 mem_realloc_data(auth_req->data, auth_req->offset);
326 /* create the request RPC_HDR */
327 make_rpc_hdr(&hdr, RPC_BIND, 0x0, get_rpc_call_id(),
328 rhdr_rb->offset, auth_req != NULL ? auth_req->offset : 0);
330 smb_io_rpc_hdr("hdr" , &hdr , rhdr, 0);
331 mem_realloc_data(rhdr->data, rhdr->offset);
333 if (rhdr->data == NULL || rhdr_rb->data == NULL)
337 /*** link rpc header, bind acknowledgment and authentication responses ***/
340 rhdr->data->offset.start = 0;
341 rhdr->data->offset.end = rhdr->offset;
342 rhdr->data->next = rhdr_rb->data;
344 if (auth_req != NULL)
346 rhdr_rb->data->offset.start = rhdr->offset;
347 rhdr_rb->data->offset.end = rhdr->offset + rhdr_rb->offset;
348 rhdr_rb->data->next = auth_req->data;
350 auth_req->data->offset.start = rhdr->offset + rhdr_rb->offset;
351 auth_req->data->offset.end = rhdr->offset + auth_req->offset + rhdr_rb->offset;
352 auth_req->data->next = NULL;
356 rhdr_rb->data->offset.start = rhdr->offset;
357 rhdr_rb->data->offset.end = rhdr->offset + rhdr_rb->offset;
358 rhdr_rb->data->next = NULL;
365 /*******************************************************************
366 creates a DCE/RPC bind request
368 - initialises the parse structure.
369 - dynamically allocates the header data structure
370 - caller is expected to free the header data structure once used.
372 ********************************************************************/
374 static BOOL create_rpc_request(prs_struct *rhdr, uint8 op_num, int data_len)
379 DEBUG(5,("create_rpc_request: opnum: 0x%x data_len: 0x%x\n",
382 /* create the rpc header RPC_HDR */
383 make_rpc_hdr(&hdr , RPC_REQUEST, RPC_FLG_FIRST | RPC_FLG_LAST,
384 get_rpc_call_id(), data_len + 0x18, 0);
386 /* create the rpc request RPC_HDR_REQ */
387 make_rpc_hdr_req(&hdr_req, data_len, op_num);
390 smb_io_rpc_hdr ("hdr ", &hdr , rhdr, 0);
391 smb_io_rpc_hdr_req("hdr_req", &hdr_req, rhdr, 0);
393 if (rhdr->data == NULL || rhdr->offset != 0x18)
396 rhdr->data->offset.start = 0;
397 rhdr->data->offset.end = rhdr->offset;
403 /****************************************************************************
404 send a request on an rpc pipe.
405 ****************************************************************************/
406 BOOL rpc_api_pipe_req(struct cli_state *cli, uint8 op_num,
407 prs_struct *data, prs_struct *rdata)
409 /* fudge this, at the moment: create the header; memcpy the data. oops. */
415 data_len = data->offset + 0x18;
416 data->data->offset.end = data->offset;
418 prs_init(&hdr , data_len, 4, SAFETY_MARGIN, False);
419 prs_init(&rparam, 0 , 4, 0 , True );
421 create_rpc_request(&hdr, op_num, data_len);
423 mem_realloc_data(hdr.data, data_len);
424 hdr.data->offset.end = data_len;
425 mem_buf_copy(mem_data(&(hdr.data), 0x18), data->data, 0, data->offset);
427 ret = rpc_api_pipe(cli, 0x0026, NULL, &hdr, &rparam, rdata);
429 prs_mem_free(&rparam);
436 /****************************************************************************
438 ****************************************************************************/
440 BOOL rpc_pipe_set_hnd_state(struct cli_state *cli, char *pipe_name, uint16 device_state)
442 BOOL state_set = False;
444 uint16 setup[2]; /* only need 2 uint16 setup parameters */
447 uint32 rparam_len, rdata_len;
449 if (pipe_name == NULL)
452 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
453 cli->nt_pipe_fnum, pipe_name, device_state));
455 /* create parameters: device state */
456 SSVAL(param, 0, device_state);
458 /* create setup parameters. */
460 setup[1] = cli->nt_pipe_fnum; /* pipe file handle. got this from an SMBOpenX. */
462 /* send the data on \PIPE\ */
463 if (cli_api_pipe(cli, "\\PIPE\\\0\0\0", 8,
464 setup, 2, 0, /* setup, length, max */
465 param, 2, 0, /* param, length, max */
466 NULL, 0, 1024, /* data, length, max */
467 &rparam, &rparam_len, /* return param, length */
468 &rdata, &rdata_len)) /* return data, length */
470 DEBUG(5, ("Set Handle state: return OK\n"));
482 /****************************************************************************
483 check the rpc bind acknowledge response
484 ****************************************************************************/
486 static BOOL valid_pipe_name(char *pipe_name, RPC_IFACE *abstract, RPC_IFACE *transfer)
490 while (pipe_names[pipe_idx].client_pipe != NULL)
492 if (strequal(pipe_name, pipe_names[pipe_idx].client_pipe ))
494 DEBUG(5,("Bind Abstract Syntax: "));
495 dump_data(5, (char*)&(pipe_names[pipe_idx].abstr_syntax),
496 sizeof(pipe_names[pipe_idx].abstr_syntax));
497 DEBUG(5,("Bind Transfer Syntax: "));
498 dump_data(5, (char*)&(pipe_names[pipe_idx].trans_syntax),
499 sizeof(pipe_names[pipe_idx].trans_syntax));
501 /* copy the required syntaxes out so we can do the right bind */
502 memcpy(transfer, &(pipe_names[pipe_idx].trans_syntax),
503 sizeof(pipe_names[pipe_idx].trans_syntax));
504 memcpy(abstract, &(pipe_names[pipe_idx].abstr_syntax),
505 sizeof(pipe_names[pipe_idx].abstr_syntax));
512 DEBUG(5,("Bind RPC Pipe[%s] unsupported\n", pipe_name));
516 /****************************************************************************
517 check the rpc bind acknowledge response
518 ****************************************************************************/
520 static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, char *pipe_name, RPC_IFACE *transfer)
524 while ((pipe_names[i].client_pipe != NULL))
526 DEBUG(6,("bind_rpc_pipe: searching pipe name: client:%s server:%s\n",
527 pipe_names[i].client_pipe , pipe_names[i].server_pipe ));
529 if ((strequal(pipe_name, pipe_names[i].client_pipe )))
531 if (strequal(hdr_ba->addr.str, pipe_names[i].server_pipe ))
533 DEBUG(5,("bind_rpc_pipe: server pipe_name found: %s\n",
534 pipe_names[i].server_pipe ));
539 DEBUG(2,("bind_rpc_pipe: pipe_name %s != expected pipe %s\n",
540 pipe_names[i].server_pipe , hdr_ba->addr.str));
550 if (pipe_names[i].server_pipe == NULL)
552 DEBUG(2,("bind_rpc_pipe: pipe name %s unsupported\n", hdr_ba->addr.str));
556 /* check the transfer syntax */
557 if (!((hdr_ba->transfer.version == transfer->version) &&
558 (memcmp(hdr_ba->transfer.data, transfer->data,
559 sizeof(transfer->version)) ==0)))
561 DEBUG(0,("bind_rpc_pipe: transfer syntax differs\n"));
565 /* lkclXXXX only accept one result: check the result(s) */
566 if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0)
568 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
569 hdr_ba->res.num_results, hdr_ba->res.reason));
572 DEBUG(5,("bind_rpc_pipe: accepted!\n"));
576 /****************************************************************************
578 ****************************************************************************/
580 BOOL rpc_pipe_bind(struct cli_state *cli, char *pipe_name,
581 RPC_IFACE *abstract, RPC_IFACE *transfer, BOOL ntlmssp_auth)
590 BOOL valid_ack = False;
592 if (pipe_name == NULL || abstract == NULL || transfer == NULL)
595 DEBUG(5,("Bind RPC Pipe[%x]: %s\n", cli->nt_pipe_fnum, pipe_name));
597 if (!valid_pipe_name(pipe_name, abstract, transfer))
600 prs_init(&hdr , 0x10 , 4, 0x0 , False);
601 prs_init(&hdr_rb , 1024 , 4, SAFETY_MARGIN, False);
602 prs_init(&auth_req, ntlmssp_auth ? 1024 : 0, 4, SAFETY_MARGIN, False);
604 prs_init(&rdata , 0 , 4, SAFETY_MARGIN, True );
605 prs_init(&rparam, 0 , 4, SAFETY_MARGIN, True );
607 create_rpc_bind_req(&hdr, &hdr_rb, ntlmssp_auth ? &auth_req : NULL,
608 abstract, transfer, global_myname, global_myworkgroup);
610 /* this is a hack due to limitations in rpc_api_pipe */
611 prs_init(&data, mem_buf_len(hdr.data), 4, 0x0, False);
612 mem_buf_copy(data.data->data, hdr.data, 0, mem_buf_len(hdr.data));
614 /* send data on \PIPE\. receive a response */
615 if (rpc_api_pipe(cli, 0x0026, NULL, &data, &rparam, &rdata))
619 DEBUG(5, ("rpc_api_pipe: return OK\n"));
621 smb_io_rpc_hdr_ba("", &hdr_ba, &rdata, 0);
623 if (rdata.offset != 0)
624 valid_ack = check_bind_response(&hdr_ba, pipe_name, transfer);
627 prs_mem_free(&data );
629 prs_mem_free(&hdr_rb );
630 prs_mem_free(&auth_req);
631 prs_mem_free(&rdata );
632 prs_mem_free(&rparam );
637 /****************************************************************************
639 ****************************************************************************/
641 BOOL cli_nt_session_open(struct cli_state *cli, char *pipe_name, BOOL encrypted)
647 /******************* open the pipe *****************/
648 if ((fnum = cli_open(cli, pipe_name, O_CREAT|O_RDWR, DENY_NONE)) == -1)
650 DEBUG(0,("cli_nt_session_open: cli_open failed on pipe %s to machine %s. \
651 Error was %s\n", pipe_name, cli->desthost, cli_errstr(cli)));
655 cli->nt_pipe_fnum = (uint16)fnum;
657 /**************** Set Named Pipe State ***************/
658 if (!rpc_pipe_set_hnd_state(cli, pipe_name, 0x4300))
660 DEBUG(0,("cli_nt_session_open: pipe hnd state failed. Error was %s\n",
662 cli_close(cli, cli->nt_pipe_fnum);
666 /******************* bind request on pipe *****************/
667 if (!rpc_pipe_bind(cli, pipe_name, &abstract, &transfer, encrypted))
669 DEBUG(0,("cli_nt_session_open: rpc bind failed. Error was %s\n", cli_errstr(cli)));
670 cli_close(cli, cli->nt_pipe_fnum);
675 * Setup the remote server name prefixed by \ and the machine account name.
678 fstrcpy(cli->srv_name_slash, "\\\\");
679 fstrcat(cli->srv_name_slash, cli->desthost);
680 strupper(cli->srv_name_slash);
682 fstrcpy(cli->clnt_name_slash, "\\\\");
683 fstrcat(cli->clnt_name_slash, global_myname);
684 strupper(cli->clnt_name_slash);
686 fstrcpy(cli->mach_acct, global_myname);
687 fstrcat(cli->mach_acct, "$");
688 strupper(cli->mach_acct);
693 /****************************************************************************
695 ****************************************************************************/
697 void cli_nt_session_close(struct cli_state *cli)
699 cli_close(cli, cli->nt_pipe_fnum);