These don't compile yet - but they are the core code in what
[sfrench/samba-autobuild/.git] / source3 / rpc_client / cli_pipe.c
1
2 /* 
3  *  Unix SMB/Netbios implementation.
4  *  Version 1.9.
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.
9  *  
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.
14  *  
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.
19  *  
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.
23  */
24
25
26 #ifdef SYSLOG
27 #undef SYSLOG
28 #endif
29
30 #include "includes.h"
31
32 extern int DEBUGLEVEL;
33 extern struct pipe_id_info pipe_names[];
34
35 /********************************************************************
36  rpc pipe call id 
37  ********************************************************************/
38
39 uint32 get_rpc_call_id(void)
40 {
41   static uint32 call_id = 1;
42   return ++call_id;
43 }
44
45 /*******************************************************************
46  uses SMBreadX to get rest of rpc data
47  ********************************************************************/
48
49 static BOOL rpc_read(struct cli_state *cli, uint16 fnum,
50                      prs_struct *rdata, uint32 data_to_read,
51                      uint32 rdata_offset)
52 {
53   int size = 0x1630;
54   int file_offset = rdata_offset;
55   int num_read;
56   char *data = rdata->data->data;
57   uint32 err;
58   uint32 new_data_size = rdata->data->data_used + data_to_read;
59
60   data += rdata_offset;
61
62   file_offset -= rdata_offset;
63
64   DEBUG(5,("rpc_read: data_to_read: %d data offset: %d file offset: %d\n",
65            data_to_read, rdata_offset, file_offset));
66
67   if (new_data_size > rdata->data->data_size)
68   {
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));
71   }
72
73   do /* read data using SMBreadX */
74   {
75     if (size > data_to_read)
76       size = data_to_read;
77
78     new_data_size = rdata->data->data_used + size;
79
80     if (new_data_size > rdata->data->data_size)
81     {
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));
84     }
85
86     num_read = cli_read(cli, fnum, data, file_offset + 0x100000, size);
87
88     DEBUG(5,("rpc_read: read offset: %d read: %d to read: %d\n",
89          file_offset, num_read, data_to_read));
90
91     data_to_read -= num_read;
92     file_offset  += num_read;
93     data         += num_read;
94
95     if (cli_error(cli, NULL, &err))
96       return False;
97
98   } while (num_read > 0 && data_to_read > 0);
99             /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */
100
101   mem_realloc_data(rdata->data, file_offset + rdata_offset);
102   rdata->data->offset.end = file_offset + rdata_offset;
103
104   DEBUG(5,("rpc_read: data supposedly left to read:0x%x\n", data_to_read));
105
106   return data_to_read == 0;
107 }
108
109 /****************************************************************************
110  checks the header
111  ****************************************************************************/
112 static BOOL rpc_check_hdr(prs_struct *rdata, uint8 *pkt_type,
113                           BOOL *first, BOOL *last, int *len)
114 {
115   RPC_HDR    rhdr;
116
117   DEBUG(5,("rpc_check_hdr: rdata->data->data_used: %d\n", rdata->data->data_used));
118
119   smb_io_rpc_hdr   ("rpc_hdr   ", &rhdr   , rdata, 0);
120
121   if (!rdata->offset || rdata->offset != 0x10)
122   {
123     DEBUG(5,("cli_pipe: error in rpc header\n"));
124     return False;
125   }
126
127   DEBUG(5,("rpc_check_hdr: (after smb_io_rpc_hdr call) rdata->data->data_used: %d\n",
128          rdata->data->data_used));
129
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;
134
135   return True;
136 }
137
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...
141
142  read the first fragment: unfortunately have to use SMBtrans for the first
143  bit, then SMBreadX for subsequent bits.
144
145  if first fragment received also wasn't the last fragment, continue
146  getting fragments until we _do_ receive the last fragment.
147
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...]
153
154  ****************************************************************************/
155
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)
159 {
160   int len;
161
162   uint16 setup[2]; /* only need 2 uint16 setup parameters */
163   uint32 err;
164   uint8 pkt_type = 0xff;
165   BOOL first = True;
166   BOOL last  = True;
167
168   /* prepare return data and params */
169
170   /* create setup parameters. */
171   setup[0] = cmd; 
172   setup[1] = fnum; /* pipe file handle.  got this from an SMBcreateX. */
173
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,
178                     2,
179                     0,
180                     data  != NULL ? 1024 : 0 ,
181                     param != NULL ? param->data->data : NULL,
182                     data  != NULL ? data ->data->data : NULL,
183                     setup,
184                     rparam != NULL ? rparam->data : NULL,
185                     rdata  != NULL ? rdata ->data : NULL))
186   {
187     DEBUG(5, ("cli_pipe: return critical error\n"));
188     return False;
189   }
190
191   if (cli_error(cli, NULL, &err))
192     return False;
193
194   if (rdata->data->data == NULL)
195     return False;
196
197   /**** parse the header: check it's a response record */
198
199   rdata->data->offset.start = 0;
200   rdata->data->offset.end   = rdata->data->data_used;
201   rdata->offset = 0;
202
203   if (!rpc_check_hdr(rdata, &pkt_type, &first, &last, &len))
204     return False;
205         
206   if (pkt_type == RPC_RESPONSE)
207   {
208     RPC_HDR_RESP rhdr_resp;
209     smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, rdata, 0);
210   }
211
212   DEBUG(5,("rpc_api_pipe: len left: %d smbtrans read: %d\n",
213          len, rdata->data->data_used));
214
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)) */
218   {
219     if (!rpc_read(cli, fnum, rdata, len, rdata->data->data_used))
220       return False;
221   }
222
223   /* only one rpc fragment, and it has been read */
224   if (first && last)
225   {
226     DEBUG(6,("rpc_api_pipe: fragment first and last both set\n"));
227     return True;
228   }
229
230   while (!last) /* read more fragments until we get the last one */
231   {
232     RPC_HDR      rhdr;
233     RPC_HDR_RESP rhdr_resp;
234     int num_read;
235     prs_struct hps;
236
237     prs_init(&hps, 0x18, 4, 0, True);
238         
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));
241
242     if (num_read != 0x18)
243       return False;
244
245     smb_io_rpc_hdr     ("rpc_hdr     ", &rhdr     , &hps, 0);
246     smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, &hps, 0);
247
248     prs_mem_free(&hps);
249
250     if (cli_error(cli, NULL, &err))
251       return False;
252
253     first = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_FIRST);
254     last  = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_LAST );
255
256     if (first)
257     {
258       DEBUG(4,("rpc_api_pipe: wierd rpc header received\n"));
259       return False;
260     }
261
262     len = rhdr.frag_len - hps.offset;
263     if (!rpc_read(cli, fnum, rdata, len, rdata->data->data_used))
264       return False;
265   }
266
267   return True;
268 }
269
270 /*******************************************************************
271  creates a DCE/RPC bind request
272
273  - initialises the parse structure.
274  - dynamically allocates the header data structure
275  - caller is expected to free the header data structure once used.
276
277  ********************************************************************/
278
279 static BOOL create_rpc_bind_req(prs_struct *rhdr,
280                                 prs_struct *rhdr_rb,
281                                 prs_struct *auth_req,
282                                 RPC_IFACE *abstract, RPC_IFACE *transfer,
283                                 char *my_name, char *domain)
284 {
285   RPC_HDR_RB        hdr_rb;
286   RPC_HDR           hdr;
287   RPC_AUTH_NTLMSSP_REQ ntlmssp_req;
288
289   /* create the bind request RPC_HDR_RB */
290   make_rpc_hdr_rb(&hdr_rb, 0x1630, 0x1630, 0x0,
291                   0x1, 0x0, 0x1, abstract, transfer);
292
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);
296
297   if (auth_req != NULL)
298   {
299     /*
300      * I have a feeling this is broken right now... JRA.
301      */
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);
306   }
307
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);
311
312   smb_io_rpc_hdr("hdr"   , &hdr   , rhdr, 0);
313   mem_realloc_data(rhdr->data, rhdr->offset);
314
315   if (rhdr->data == NULL || rhdr_rb->data == NULL)
316     return False;
317
318   /***/
319   /*** link rpc header, bind acknowledgment and authentication responses ***/
320   /***/
321
322   rhdr->data->offset.start = 0;
323   rhdr->data->offset.end   = rhdr->offset;
324   rhdr->data->next         = rhdr_rb->data;
325
326   if (auth_req != NULL)
327   {
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;
331
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;
335   }
336   else
337   {
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;
341   }
342
343   return True;
344 }
345
346
347 /*******************************************************************
348  creates a DCE/RPC bind request
349
350  - initialises the parse structure.
351  - dynamically allocates the header data structure
352  - caller is expected to free the header data structure once used.
353
354  ********************************************************************/
355
356 static BOOL create_rpc_request(prs_struct *rhdr, uint8 op_num, int data_len)
357 {
358   RPC_HDR_REQ hdr_req;
359   RPC_HDR     hdr;
360
361   DEBUG(5,("create_rpc_request: opnum: 0x%x data_len: 0x%x\n",
362        op_num, data_len));
363
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);
367
368   /* create the rpc request RPC_HDR_REQ */
369   make_rpc_hdr_req(&hdr_req, data_len, op_num);
370
371   /* stream-time... */
372   smb_io_rpc_hdr    ("hdr    ", &hdr    , rhdr, 0);
373   smb_io_rpc_hdr_req("hdr_req", &hdr_req, rhdr, 0);
374
375   if (rhdr->data == NULL || rhdr->offset != 0x18)
376     return False;
377
378   rhdr->data->offset.start = 0;
379   rhdr->data->offset.end   = rhdr->offset;
380
381   return True;
382 }
383
384
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)
390 {
391   /* fudge this, at the moment: create the header; memcpy the data.  oops. */
392   prs_struct rparam;
393   prs_struct hdr;
394   int data_len;
395   BOOL ret;
396
397   data_len               = data->offset + 0x18;
398   data->data->offset.end = data->offset;
399
400   prs_init(&hdr   , data_len, 4, SAFETY_MARGIN, False);
401   prs_init(&rparam, 0       , 4, 0            , True );
402
403   create_rpc_request(&hdr, op_num, data_len);
404
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);
408
409   ret = rpc_api_pipe(cli, 0x0026, fnum, NULL, &hdr, &rparam, rdata);
410
411   prs_mem_free(&rparam);
412   prs_mem_free(&hdr);
413
414   return ret;
415 }
416
417
418 /****************************************************************************
419 do an rpc bind
420 ****************************************************************************/
421
422 BOOL rpc_pipe_set_hnd_state(struct cli_state *cli, char *pipe_name, 
423                             uint16 fnum, uint16 device_state)
424 {
425   prs_struct param;
426   prs_struct rdata;
427   prs_struct rparam;
428   BOOL state_set = False;
429   uint16 setup[2]; /* only need 2 uint16 setup parameters */
430
431   if (pipe_name == NULL)
432     return False;
433
434   prs_init(&param , 2, 4, 0            , False);
435   prs_init(&rdata , 0, 4, SAFETY_MARGIN, True );
436   prs_init(&rparam, 0, 4, SAFETY_MARGIN, True );
437
438   param.data->offset.start = 0;
439   param.data->offset.end   = 2;
440
441   DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
442               fnum, pipe_name, device_state));
443
444   /* create data parameters: device state */
445   SSVAL(param.data->data, 0, device_state);
446
447   /* create setup parameters. */
448   setup[0] = 0x0001; 
449   setup[1] = fnum; /* pipe file handle.  got this from an SMBcreateX. */
450
451   /* send the data on \PIPE\ */
452   if (cli_api_pipe(cli, "\\PIPE\\\0\0\0", 8,
453                    2, 0, 2,
454                    0, 1024,
455                    param.data->data, NULL, setup,
456                    rparam.data, rdata.data))
457   {
458     DEBUG(5, ("Set Handle state: return OK\n"));
459     state_set = True;
460   }
461
462   prs_mem_free(&param );
463   prs_mem_free(&rparam);
464   prs_mem_free(&rdata );
465
466   return state_set;
467 }
468
469 /****************************************************************************
470  check the rpc bind acknowledge response
471 ****************************************************************************/
472
473 static BOOL valid_pipe_name(char *pipe_name, RPC_IFACE *abstract, RPC_IFACE *transfer)
474 {
475   int pipe_idx = 0;
476
477   while (pipe_names[pipe_idx].client_pipe != NULL)
478   {
479     if (strequal(pipe_name, pipe_names[pipe_idx].client_pipe ))
480     {
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));
487
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));
493
494       return True;
495     }
496     pipe_idx++;
497   };
498
499   DEBUG(5,("Bind RPC Pipe[%s] unsupported\n", pipe_name));
500   return False;
501 }
502
503 /****************************************************************************
504  check the rpc bind acknowledge response
505 ****************************************************************************/
506
507 static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, char *pipe_name, RPC_IFACE *transfer)
508 {
509   int i = 0;
510
511   while ((pipe_names[i].client_pipe != NULL))
512   {
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 ));
515
516     if ((strequal(pipe_name, pipe_names[i].client_pipe )))
517     {
518       if (strequal(hdr_ba->addr.str, pipe_names[i].server_pipe ))
519       {
520         DEBUG(5,("bind_rpc_pipe: server pipe_name found: %s\n",
521               pipe_names[i].server_pipe ));
522         break;
523       }
524       else
525       {
526         DEBUG(2,("bind_rpc_pipe: pipe_name %s != expected pipe %s\n",
527            pipe_names[i].server_pipe , hdr_ba->addr.str));
528         return False;
529       }
530     }
531     else
532     {
533       i++;
534     }
535   }
536
537   if (pipe_names[i].server_pipe == NULL)
538   {
539     DEBUG(2,("bind_rpc_pipe: pipe name %s unsupported\n", hdr_ba->addr.str));
540     return False;
541   }
542
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)))
547   {
548     DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
549     return False;
550   }
551         
552   /* lkclXXXX only accept one result: check the result(s) */
553   if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0)
554   {
555     DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
556             hdr_ba->res.num_results, hdr_ba->res.reason));
557   }
558         
559   DEBUG(5,("bind_rpc_pipe: accepted!\n"));
560   return True;
561 }
562
563 /****************************************************************************
564 do an rpc bind
565 ****************************************************************************/
566
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)
570 {
571   prs_struct hdr;
572   prs_struct hdr_rb;
573   prs_struct auth_req;
574   prs_struct data;
575   prs_struct rdata;
576   prs_struct rparam;
577
578   BOOL valid_ack = False;
579
580   if (pipe_name == NULL || abstract == NULL || transfer == NULL)
581     return False;
582
583   DEBUG(5,("Bind RPC Pipe[%x]: %s\n", fnum, pipe_name));
584
585   if (!valid_pipe_name(pipe_name, abstract, transfer))
586     return False;
587
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);
591
592   prs_init(&rdata , 0   , 4, SAFETY_MARGIN, True );
593   prs_init(&rparam, 0   , 4, SAFETY_MARGIN, True );
594
595   create_rpc_bind_req(&hdr, &hdr_rb, ntlmssp_auth ? &auth_req : NULL,
596                       abstract, transfer, my_name, domain);
597
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));
601
602   /* send data on \PIPE\.  receive a response */
603   if (rpc_api_pipe(cli, 0x0026, fnum, NULL, &data, &rparam, &rdata))
604   {
605     RPC_HDR_BA hdr_ba;
606
607     DEBUG(5, ("rpc_api_pipe: return OK\n"));
608
609     smb_io_rpc_hdr_ba("", &hdr_ba, &rdata, 0);
610
611     if (rdata.offset != 0)
612       valid_ack = check_bind_response(&hdr_ba, pipe_name, transfer);
613   }
614
615   prs_mem_free(&data    );
616   prs_mem_free(&hdr     );
617   prs_mem_free(&hdr_rb  );
618   prs_mem_free(&auth_req);
619   prs_mem_free(&rdata   );
620   prs_mem_free(&rparam  );
621
622   return valid_ack;
623 }
624
625 /****************************************************************************
626  open a session
627  ****************************************************************************/
628
629 BOOL do_session_open(struct cli_state *cli, char *pipe_name, uint16 *fnum)
630 {
631   RPC_IFACE abstract;
632   RPC_IFACE transfer;
633
634   /******************* open the pipe *****************/
635   if (((*fnum) = cli_open(cli, pipe_name, O_CREAT|O_WRONLY, DENY_NONE)) == 0xffff)
636   {
637     DEBUG(1,("do_session_open: cli_open failed\n"));
638     return False;
639   }
640
641   /**************** Set Named Pipe State ***************/
642   if (!rpc_pipe_set_hnd_state(cli, pipe_name, (*fnum), 0x4300))
643   {
644     DEBUG(1,("do_session_open: pipe hnd state failed\n"));
645     return False;
646   }
647
648   /******************* bind request on pipe *****************/
649   if (!rpc_pipe_bind(cli, pipe_name, (*fnum), &abstract, &transfer,
650                      False, NULL, NULL))
651   {
652     DEBUG(1,("do_session_open: rpc bind failed\n"));
653     return False;
654   }
655
656   return True;
657 }
658
659 /****************************************************************************
660  open an encrypted session
661  ****************************************************************************/
662
663 BOOL do_ntlm_session_open(struct cli_state *cli, char *pipe_name, uint16 *fnum,
664                           char *my_name, char *domain)
665 {
666   RPC_IFACE abstract;
667   RPC_IFACE transfer;
668
669   /******************* open the pipe *****************/
670   if (((*fnum) = cli_open(cli, pipe_name, O_CREAT|O_WRONLY, DENY_NONE)) == 0xffff)
671   {
672     DEBUG(1,("do_ntlm_session_open: cli_open failed\n"));
673     return False;
674   }
675
676   /**************** Set Named Pipe State ***************/
677   if (!rpc_pipe_set_hnd_state(cli, pipe_name, (*fnum), 0x4300))
678   {
679     DEBUG(1,("do_ntlm_session_open: pipe hnd state failed\n"));
680     return False;
681   }
682
683   /******************* bind request on pipe *****************/
684   if (!rpc_pipe_bind(cli, pipe_name, (*fnum), &abstract, &transfer,
685                      True, my_name, domain))
686   {
687     DEBUG(1,("do_ntlm_session_open: rpc bind failed\n"));
688     return False;
689   }
690
691   return True;
692 }
693
694 /****************************************************************************
695 close the session
696 ****************************************************************************/
697
698 void do_session_close(struct cli_state *cli, uint16 fnum)
699 {
700   if (fnum != 0xffff)
701   {
702     cli_close(cli, fnum);
703   }
704 }