3e03887bfdb00c842aa2f461dbab7bac2271e392
[kai/samba.git] / source3 / rpc_client / cli_pipe.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Largely rewritten by Jeremy Allison             2005.
5  *  
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 3 of the License, or
9  *  (at your option) any later version.
10  *  
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *  
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "includes.h"
21
22 #undef DBGC_CLASS
23 #define DBGC_CLASS DBGC_RPC_CLI
24
25 extern struct pipe_id_info pipe_names[];
26
27 /********************************************************************
28  Map internal value to wire value.
29  ********************************************************************/
30
31 static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type)
32 {
33         switch (auth_type) {
34
35         case PIPE_AUTH_TYPE_NONE:
36                 return RPC_ANONYMOUS_AUTH_TYPE;
37
38         case PIPE_AUTH_TYPE_NTLMSSP:
39                 return RPC_NTLMSSP_AUTH_TYPE;
40
41         case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
42         case PIPE_AUTH_TYPE_SPNEGO_KRB5:
43                 return RPC_SPNEGO_AUTH_TYPE;
44
45         case PIPE_AUTH_TYPE_SCHANNEL:
46                 return RPC_SCHANNEL_AUTH_TYPE;
47
48         case PIPE_AUTH_TYPE_KRB5:
49                 return RPC_KRB5_AUTH_TYPE;
50
51         default:
52                 DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe "
53                         "auth type %u\n",
54                         (unsigned int)auth_type ));
55                 break;
56         }
57         return -1;
58 }
59
60 /********************************************************************
61  Rpc pipe call id.
62  ********************************************************************/
63
64 static uint32 get_rpc_call_id(void)
65 {
66         static uint32 call_id = 0;
67         return ++call_id;
68 }
69
70 /*******************************************************************
71  Use SMBreadX to get rest of one fragment's worth of rpc data.
72  Will expand the current_pdu struct to the correct size.
73  ********************************************************************/
74
75 static NTSTATUS rpc_read(struct rpc_pipe_client *cli,
76                         prs_struct *current_pdu,
77                         uint32 data_to_read,
78                         uint32 *current_pdu_offset)
79 {
80         size_t size = (size_t)cli->max_recv_frag;
81         uint32 stream_offset = 0;
82         ssize_t num_read;
83         char *pdata;
84         ssize_t extra_data_size = ((ssize_t)*current_pdu_offset) + ((ssize_t)data_to_read) - (ssize_t)prs_data_size(current_pdu);
85
86         DEBUG(5,("rpc_read: data_to_read: %u current_pdu offset: %u extra_data_size: %d\n",
87                 (unsigned int)data_to_read, (unsigned int)*current_pdu_offset, (int)extra_data_size ));
88
89         /*
90          * Grow the buffer if needed to accommodate the data to be read.
91          */
92
93         if (extra_data_size > 0) {
94                 if(!prs_force_grow(current_pdu, (uint32)extra_data_size)) {
95                         DEBUG(0,("rpc_read: Failed to grow parse struct by %d bytes.\n", (int)extra_data_size ));
96                         return NT_STATUS_NO_MEMORY;
97                 }
98                 DEBUG(5,("rpc_read: grew buffer by %d bytes to %u\n", (int)extra_data_size, prs_data_size(current_pdu) ));
99         }
100
101         pdata = prs_data_p(current_pdu) + *current_pdu_offset;
102
103         do {
104                 /* read data using SMBreadX */
105                 if (size > (size_t)data_to_read) {
106                         size = (size_t)data_to_read;
107                 }
108
109                 num_read = cli_read(cli->cli, cli->fnum, pdata,
110                                          (off_t)stream_offset, size);
111
112                 DEBUG(5,("rpc_read: num_read = %d, read offset: %u, to read: %u\n",
113                         (int)num_read, (unsigned int)stream_offset, (unsigned int)data_to_read));
114
115                 /*
116                  * A dos error of ERRDOS/ERRmoredata is not an error.
117                  */
118                 if (cli_is_dos_error(cli->cli)) {
119                         uint32 ecode;
120                         uint8 eclass;
121                         cli_dos_error(cli->cli, &eclass, &ecode);
122                         if (eclass != ERRDOS && ecode != ERRmoredata) {
123                                 DEBUG(0,("rpc_read: DOS Error %d/%u (%s) in cli_read on pipe %s\n",
124                                         eclass, (unsigned int)ecode,
125                                         cli_errstr(cli->cli),
126                                         cli->pipe_name ));
127                                 return dos_to_ntstatus(eclass, ecode);
128                         }
129                 }
130
131                 /*
132                  * Likewise for NT_STATUS_BUFFER_TOO_SMALL
133                  */
134                 if (cli_is_nt_error(cli->cli)) {
135                         if (!NT_STATUS_EQUAL(cli_nt_error(cli->cli), NT_STATUS_BUFFER_TOO_SMALL)) {
136                                 DEBUG(0,("rpc_read: Error (%s) in cli_read on pipe %s\n",
137                                         nt_errstr(cli_nt_error(cli->cli)),
138                                         cli->pipe_name ));
139                                 return cli_nt_error(cli->cli);
140                         }
141                 }
142
143                 if (num_read == -1) {
144                         DEBUG(0,("rpc_read: Error - cli_read on pipe %s returned -1\n",
145                                 cli->pipe_name ));
146                         return cli_get_nt_error(cli->cli);
147                 }
148
149                 data_to_read -= num_read;
150                 stream_offset += num_read;
151                 pdata += num_read;
152
153         } while (num_read > 0 && data_to_read > 0);
154         /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */
155
156         /*
157          * Update the current offset into current_pdu by the amount read.
158          */
159         *current_pdu_offset += stream_offset;
160         return NT_STATUS_OK;
161 }
162
163 /****************************************************************************
164  Try and get a PDU's worth of data from current_pdu. If not, then read more
165  from the wire.
166  ****************************************************************************/
167
168 static NTSTATUS cli_pipe_get_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
169 {
170         NTSTATUS ret = NT_STATUS_OK;
171         uint32 current_pdu_len = prs_data_size(current_pdu);
172
173         /* Ensure we have at least RPC_HEADER_LEN worth of data to parse. */
174         if (current_pdu_len < RPC_HEADER_LEN) {
175                 /* rpc_read expands the current_pdu struct as neccessary. */
176                 ret = rpc_read(cli, current_pdu, RPC_HEADER_LEN - current_pdu_len, &current_pdu_len);
177                 if (!NT_STATUS_IS_OK(ret)) {
178                         return ret;
179                 }
180         }
181
182         /* This next call sets the endian bit correctly in current_pdu. */
183         /* We will propagate this to rbuf later. */
184         if(!smb_io_rpc_hdr("rpc_hdr   ", prhdr, current_pdu, 0)) {
185                 DEBUG(0,("cli_pipe_get_current_pdu: Failed to unmarshall RPC_HDR.\n"));
186                 return NT_STATUS_BUFFER_TOO_SMALL;
187         }
188
189         /* Ensure we have frag_len bytes of data. */
190         if (current_pdu_len < prhdr->frag_len) {
191                 /* rpc_read expands the current_pdu struct as neccessary. */
192                 ret = rpc_read(cli, current_pdu, (uint32)prhdr->frag_len - current_pdu_len, &current_pdu_len);
193                 if (!NT_STATUS_IS_OK(ret)) {
194                         return ret;
195                 }
196         }
197
198         if (current_pdu_len < prhdr->frag_len) {
199                 return NT_STATUS_BUFFER_TOO_SMALL;
200         }
201
202         return NT_STATUS_OK;
203 }
204
205 /****************************************************************************
206  NTLMSSP specific sign/seal.
207  Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
208  In fact I should probably abstract these into identical pieces of code... JRA.
209  ****************************************************************************/
210
211 static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
212                                 prs_struct *current_pdu,
213                                 uint8 *p_ss_padding_len)
214 {
215         RPC_HDR_AUTH auth_info;
216         uint32 save_offset = prs_offset(current_pdu);
217         uint32 auth_len = prhdr->auth_len;
218         NTLMSSP_STATE *ntlmssp_state = cli->auth.a_u.ntlmssp_state;
219         unsigned char *data = NULL;
220         size_t data_len;
221         unsigned char *full_packet_data = NULL;
222         size_t full_packet_data_len;
223         DATA_BLOB auth_blob;
224         NTSTATUS status;
225
226         if (cli->auth.auth_level == PIPE_AUTH_LEVEL_NONE || cli->auth.auth_level == PIPE_AUTH_LEVEL_CONNECT) {
227                 return NT_STATUS_OK;
228         }
229
230         if (!ntlmssp_state) {
231                 return NT_STATUS_INVALID_PARAMETER;
232         }
233
234         /* Ensure there's enough data for an authenticated response. */
235         if ((auth_len > RPC_MAX_SIGN_SIZE) ||
236                         (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
237                 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n",
238                         (unsigned int)auth_len ));
239                 return NT_STATUS_BUFFER_TOO_SMALL;
240         }
241
242         /*
243          * We need the full packet data + length (minus auth stuff) as well as the packet data + length
244          * after the RPC header.
245          * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
246          * functions as NTLMv2 checks the rpc headers also.
247          */
248
249         data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN);
250         data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len);
251
252         full_packet_data = (unsigned char *)prs_data_p(current_pdu);
253         full_packet_data_len = prhdr->frag_len - auth_len;
254
255         /* Pull the auth header and the following data into a blob. */
256         if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
257                 DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n",
258                         (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len ));
259                 return NT_STATUS_BUFFER_TOO_SMALL;
260         }
261
262         if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
263                 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n"));
264                 return NT_STATUS_BUFFER_TOO_SMALL;
265         }
266
267         auth_blob.data = (unsigned char *)prs_data_p(current_pdu) + prs_offset(current_pdu);
268         auth_blob.length = auth_len;
269
270         switch (cli->auth.auth_level) {
271                 case PIPE_AUTH_LEVEL_PRIVACY:
272                         /* Data is encrypted. */
273                         status = ntlmssp_unseal_packet(ntlmssp_state,
274                                                         data, data_len,
275                                                         full_packet_data,
276                                                         full_packet_data_len,
277                                                         &auth_blob);
278                         if (!NT_STATUS_IS_OK(status)) {
279                                 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
280                                         "packet from remote machine %s on pipe %s "
281                                         "fnum 0x%x. Error was %s.\n",
282                                         cli->desthost,
283                                         cli->pipe_name,
284                                         (unsigned int)cli->fnum,
285                                         nt_errstr(status) ));
286                                 return status;
287                         }
288                         break;
289                 case PIPE_AUTH_LEVEL_INTEGRITY:
290                         /* Data is signed. */
291                         status = ntlmssp_check_packet(ntlmssp_state,
292                                                         data, data_len,
293                                                         full_packet_data,
294                                                         full_packet_data_len,
295                                                         &auth_blob);
296                         if (!NT_STATUS_IS_OK(status)) {
297                                 DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
298                                         "packet from remote machine %s on pipe %s "
299                                         "fnum 0x%x. Error was %s.\n",
300                                         cli->desthost,
301                                         cli->pipe_name,
302                                         (unsigned int)cli->fnum,
303                                         nt_errstr(status) ));
304                                 return status;
305                         }
306                         break;
307                 default:
308                         DEBUG(0,("cli_pipe_verify_ntlmssp: unknown internal auth level %d\n",
309                                 cli->auth.auth_level ));
310                         return NT_STATUS_INVALID_INFO_CLASS;
311         }
312
313         /*
314          * Return the current pointer to the data offset.
315          */
316
317         if(!prs_set_offset(current_pdu, save_offset)) {
318                 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
319                         (unsigned int)save_offset ));
320                 return NT_STATUS_BUFFER_TOO_SMALL;
321         }
322
323         /*
324          * Remember the padding length. We must remove it from the real data
325          * stream once the sign/seal is done.
326          */
327
328         *p_ss_padding_len = auth_info.auth_pad_len;
329
330         return NT_STATUS_OK;
331 }
332
333 /****************************************************************************
334  schannel specific sign/seal.
335  ****************************************************************************/
336
337 static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
338                                 prs_struct *current_pdu,
339                                 uint8 *p_ss_padding_len)
340 {
341         RPC_HDR_AUTH auth_info;
342         RPC_AUTH_SCHANNEL_CHK schannel_chk;
343         uint32 auth_len = prhdr->auth_len;
344         uint32 save_offset = prs_offset(current_pdu);
345         struct schannel_auth_struct *schannel_auth = cli->auth.a_u.schannel_auth;
346         uint32 data_len;
347
348         if (cli->auth.auth_level == PIPE_AUTH_LEVEL_NONE || cli->auth.auth_level == PIPE_AUTH_LEVEL_CONNECT) {
349                 return NT_STATUS_OK;
350         }
351
352         if (auth_len != RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
353                 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len ));
354                 return NT_STATUS_INVALID_PARAMETER;
355         }
356
357         if (!schannel_auth) {
358                 return NT_STATUS_INVALID_PARAMETER;
359         }
360
361         /* Ensure there's enough data for an authenticated response. */
362         if ((auth_len > RPC_MAX_SIGN_SIZE) ||
363                         (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
364                 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n",
365                         (unsigned int)auth_len ));
366                 return NT_STATUS_INVALID_PARAMETER;
367         }
368
369         data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;
370
371         if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
372                 DEBUG(0,("cli_pipe_verify_schannel: cannot move offset to %u.\n",
373                         (unsigned int)RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len ));
374                 return NT_STATUS_BUFFER_TOO_SMALL;
375         }
376                                                                                                                              
377         if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
378                 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n"));
379                 return NT_STATUS_BUFFER_TOO_SMALL;
380         }
381
382         if (auth_info.auth_type != RPC_SCHANNEL_AUTH_TYPE) {
383                 DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n",
384                         auth_info.auth_type));
385                 return NT_STATUS_BUFFER_TOO_SMALL;
386         }
387
388         if(!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
389                                 &schannel_chk, current_pdu, 0)) {
390                 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n"));
391                 return NT_STATUS_BUFFER_TOO_SMALL;
392         }
393
394         if (!schannel_decode(schannel_auth,
395                         cli->auth.auth_level,
396                         SENDER_IS_ACCEPTOR,
397                         &schannel_chk,
398                         prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN,
399                         data_len)) {
400                 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
401                                 "Connection to remote machine %s "
402                                 "pipe %s fnum 0x%x.\n",
403                                 cli->desthost,
404                                 cli->pipe_name,
405                                 (unsigned int)cli->fnum ));
406                 return NT_STATUS_INVALID_PARAMETER;
407         }
408
409         /* The sequence number gets incremented on both send and receive. */
410         schannel_auth->seq_num++;
411
412         /*
413          * Return the current pointer to the data offset.
414          */
415
416         if(!prs_set_offset(current_pdu, save_offset)) {
417                 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
418                         (unsigned int)save_offset ));
419                 return NT_STATUS_BUFFER_TOO_SMALL;
420         }
421
422         /*
423          * Remember the padding length. We must remove it from the real data
424          * stream once the sign/seal is done.
425          */
426
427         *p_ss_padding_len = auth_info.auth_pad_len;
428
429         return NT_STATUS_OK;
430 }
431
432 /****************************************************************************
433  Do the authentication checks on an incoming pdu. Check sign and unseal etc.
434  ****************************************************************************/
435
436 static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
437                                 prs_struct *current_pdu,
438                                 uint8 *p_ss_padding_len)
439 {
440         NTSTATUS ret = NT_STATUS_OK;
441
442         /* Paranioa checks for auth_len. */
443         if (prhdr->auth_len) {
444                 if (prhdr->auth_len > prhdr->frag_len) {
445                         return NT_STATUS_INVALID_PARAMETER;
446                 }
447
448                 if (prhdr->auth_len + RPC_HDR_AUTH_LEN < prhdr->auth_len ||
449                                 prhdr->auth_len + RPC_HDR_AUTH_LEN < RPC_HDR_AUTH_LEN) {
450                         /* Integer wrap attempt. */
451                         return NT_STATUS_INVALID_PARAMETER;
452                 }
453         }
454
455         /*
456          * Now we have a complete RPC request PDU fragment, try and verify any auth data.
457          */
458
459         switch(cli->auth.auth_type) {
460                 case PIPE_AUTH_TYPE_NONE:
461                         if (prhdr->auth_len) {
462                                 DEBUG(3, ("cli_pipe_validate_rpc_response: Connection to remote machine %s "
463                                         "pipe %s fnum 0x%x - got non-zero auth len %u.\n",
464                                         cli->desthost,
465                                         cli->pipe_name,
466                                         (unsigned int)cli->fnum,
467                                         (unsigned int)prhdr->auth_len ));
468                                 return NT_STATUS_INVALID_PARAMETER;
469                         }
470                         break;
471
472                 case PIPE_AUTH_TYPE_NTLMSSP:
473                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
474                         ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len);
475                         if (!NT_STATUS_IS_OK(ret)) {
476                                 return ret;
477                         }
478                         break;
479
480                 case PIPE_AUTH_TYPE_SCHANNEL:
481                         ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len);
482                         if (!NT_STATUS_IS_OK(ret)) {
483                                 return ret;
484                         }
485                         break;
486
487                 case PIPE_AUTH_TYPE_KRB5:
488                 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
489                 default:
490                         DEBUG(3, ("cli_pipe_validate_rpc_response: Connection to remote machine %s "
491                                 "pipe %s fnum %x - unknown internal auth type %u.\n",
492                                 cli->desthost,
493                                 cli->pipe_name,
494                                 (unsigned int)cli->fnum,
495                                 cli->auth.auth_type ));
496                         return NT_STATUS_INVALID_INFO_CLASS;
497         }
498
499         return NT_STATUS_OK;
500 }
501
502 /****************************************************************************
503  Do basic authentication checks on an incoming pdu.
504  ****************************************************************************/
505
506 static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
507                         prs_struct *current_pdu,
508                         uint8 expected_pkt_type,
509                         char **ppdata,
510                         uint32 *pdata_len,
511                         prs_struct *return_data)
512 {
513
514         NTSTATUS ret = NT_STATUS_OK;
515         uint32 current_pdu_len = prs_data_size(current_pdu);
516
517         if (current_pdu_len != prhdr->frag_len) {
518                 DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n",
519                         (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_len ));
520                 return NT_STATUS_INVALID_PARAMETER;
521         }
522
523         /*
524          * Point the return values at the real data including the RPC
525          * header. Just in case the caller wants it.
526          */
527         *ppdata = prs_data_p(current_pdu);
528         *pdata_len = current_pdu_len;
529
530         /* Ensure we have the correct type. */
531         switch (prhdr->pkt_type) {
532                 case RPC_ALTCONTRESP:
533                 case RPC_BINDACK:
534
535                         /* Alter context and bind ack share the same packet definitions. */
536                         break;
537
538
539                 case RPC_RESPONSE:
540                 {
541                         RPC_HDR_RESP rhdr_resp;
542                         uint8 ss_padding_len = 0;
543
544                         if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
545                                 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
546                                 return NT_STATUS_BUFFER_TOO_SMALL;
547                         }
548
549                         /* Here's where we deal with incoming sign/seal. */
550                         ret = cli_pipe_validate_rpc_response(cli, prhdr,
551                                         current_pdu, &ss_padding_len);
552                         if (!NT_STATUS_IS_OK(ret)) {
553                                 return ret;
554                         }
555
556                         /* Point the return values at the NDR data. Remember to remove any ss padding. */
557                         *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
558
559                         if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) {
560                                 return NT_STATUS_BUFFER_TOO_SMALL;
561                         }
562
563                         *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len;
564
565                         /* Remember to remove the auth footer. */
566                         if (prhdr->auth_len) {
567                                 /* We've already done integer wrap tests on auth_len in
568                                         cli_pipe_validate_rpc_response(). */
569                                 if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_len) {
570                                         return NT_STATUS_BUFFER_TOO_SMALL;
571                                 }
572                                 *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len);
573                         }
574
575                         DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n",
576                                 current_pdu_len, *pdata_len, ss_padding_len ));
577
578                         /*
579                          * If this is the first reply, and the allocation hint is reasonably, try and
580                          * set up the return_data parse_struct to the correct size.
581                          */
582
583                         if ((prs_data_size(return_data) == 0) && rhdr_resp.alloc_hint && (rhdr_resp.alloc_hint < 15*1024*1024)) {
584                                 if (!prs_set_buffer_size(return_data, rhdr_resp.alloc_hint)) {
585                                         DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u "
586                                                 "too large to allocate\n",
587                                                 (unsigned int)rhdr_resp.alloc_hint ));
588                                         return NT_STATUS_NO_MEMORY;
589                                 }
590                         }
591
592                         break;
593                 }
594
595                 case RPC_BINDNACK:
596                         DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK received from remote machine %s "
597                                 "pipe %s fnum 0x%x!\n",
598                                 cli->desthost,
599                                 cli->pipe_name,
600                                 (unsigned int)cli->fnum));
601                         /* Use this for now... */
602                         return NT_STATUS_NETWORK_ACCESS_DENIED;
603
604                 case RPC_FAULT:
605                 {
606                         RPC_HDR_RESP rhdr_resp;
607                         RPC_HDR_FAULT fault_resp;
608
609                         if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
610                                 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
611                                 return NT_STATUS_BUFFER_TOO_SMALL;
612                         }
613
614                         if(!smb_io_rpc_hdr_fault("fault", &fault_resp, current_pdu, 0)) {
615                                 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n"));
616                                 return NT_STATUS_BUFFER_TOO_SMALL;
617                         }
618
619                         DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault code %s received from remote machine %s "
620                                 "pipe %s fnum 0x%x!\n",
621                                 dcerpc_errstr(NT_STATUS_V(fault_resp.status)),
622                                 cli->desthost,
623                                 cli->pipe_name,
624                                 (unsigned int)cli->fnum));
625                         if (NT_STATUS_IS_OK(fault_resp.status)) {
626                                 return NT_STATUS_UNSUCCESSFUL;
627                         } else {
628                                 return fault_resp.status;
629                         }
630                         
631                 }
632
633                 default:
634                         DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
635                                 "from remote machine %s pipe %s fnum 0x%x!\n",
636                                 (unsigned int)prhdr->pkt_type,
637                                 cli->desthost,
638                                 cli->pipe_name,
639                                 (unsigned int)cli->fnum));
640                         return NT_STATUS_INVALID_INFO_CLASS;
641         }
642
643         if (prhdr->pkt_type != expected_pkt_type) {
644                 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to remote machine %s "
645                         "pipe %s fnum %x got an unexpected RPC packet "
646                         "type - %u, not %u\n",
647                         cli->desthost,
648                         cli->pipe_name,
649                         (unsigned int)cli->fnum,
650                         prhdr->pkt_type,
651                         expected_pkt_type));
652                 return NT_STATUS_INVALID_INFO_CLASS;
653         }
654
655         /* Do this just before return - we don't want to modify any rpc header
656            data before now as we may have needed to do cryptographic actions on
657            it before. */
658
659         if ((prhdr->pkt_type == RPC_BINDACK) && !(prhdr->flags & RPC_FLG_LAST)) {
660                 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
661                         "setting fragment first/last ON.\n"));
662                 prhdr->flags |= RPC_FLG_FIRST|RPC_FLG_LAST;
663         }
664
665         return NT_STATUS_OK;
666 }
667
668 /****************************************************************************
669  Ensure we eat the just processed pdu from the current_pdu prs_struct.
670  Normally the frag_len and buffer size will match, but on the first trans
671  reply there is a theoretical chance that buffer size > frag_len, so we must
672  deal with that.
673  ****************************************************************************/
674
675 static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
676 {
677         uint32 current_pdu_len = prs_data_size(current_pdu);
678
679         if (current_pdu_len < prhdr->frag_len) {
680                 return NT_STATUS_BUFFER_TOO_SMALL;
681         }
682
683         /* Common case. */
684         if (current_pdu_len == (uint32)prhdr->frag_len) {
685                 prs_mem_free(current_pdu);
686                 prs_init_empty(current_pdu, prs_get_mem_context(current_pdu), UNMARSHALL);
687                 /* Make current_pdu dynamic with no memory. */
688                 prs_give_memory(current_pdu, 0, 0, True);
689                 return NT_STATUS_OK;
690         }
691
692         /*
693          * Oh no ! More data in buffer than we processed in current pdu.
694          * Cheat. Move the data down and shrink the buffer.
695          */
696
697         memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len,
698                         current_pdu_len - prhdr->frag_len);
699
700         /* Remember to set the read offset back to zero. */
701         prs_set_offset(current_pdu, 0);
702
703         /* Shrink the buffer. */
704         if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) {
705                 return NT_STATUS_BUFFER_TOO_SMALL;
706         }
707
708         return NT_STATUS_OK;
709 }
710
711 /****************************************************************************
712  Send data on an rpc pipe via trans. The prs_struct data must be the last
713  pdu fragment of an NDR data stream.
714
715  Receive response data from an rpc pipe, which may be large...
716
717  Read the first fragment: unfortunately have to use SMBtrans for the first
718  bit, then SMBreadX for subsequent bits.
719
720  If first fragment received also wasn't the last fragment, continue
721  getting fragments until we _do_ receive the last fragment.
722
723  Request/Response PDU's look like the following...
724
725  |<------------------PDU len----------------------------------------------->|
726  |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
727
728  +------------+-----------------+-------------+---------------+-------------+
729  | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR      | AUTH DATA   |
730  +------------+-----------------+-------------+---------------+-------------+
731
732  Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
733  signing & sealing being negotiated.
734
735  ****************************************************************************/
736
737 static NTSTATUS rpc_api_pipe(struct rpc_pipe_client *cli,
738                         prs_struct *data, /* Outgoing pdu fragment, already formatted for send. */
739                         prs_struct *rbuf, /* Incoming reply - return as an NDR stream. */
740                         uint8 expected_pkt_type)
741 {
742         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
743         char *rparam = NULL;
744         uint32 rparam_len = 0;
745         uint16 setup[2];
746         char *pdata = prs_data_p(data);
747         uint32 data_len = prs_offset(data);
748         char *prdata = NULL;
749         uint32 rdata_len = 0;
750         uint32 max_data = cli->max_xmit_frag ? cli->max_xmit_frag : RPC_MAX_PDU_FRAG_LEN;
751         uint32 current_rbuf_offset = 0;
752         prs_struct current_pdu;
753         
754 #ifdef DEVELOPER
755         /* Ensure we're not sending too much. */
756         SMB_ASSERT(data_len <= max_data);
757 #endif
758
759         /* Set up the current pdu parse struct. */
760         prs_init_empty(&current_pdu, prs_get_mem_context(rbuf), UNMARSHALL);
761
762         /* Create setup parameters - must be in native byte order. */
763         setup[0] = TRANSACT_DCERPCCMD; 
764         setup[1] = cli->fnum; /* Pipe file handle. */
765
766         DEBUG(5,("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x\n",
767                 cli->desthost,
768                 cli->pipe_name,
769                 (unsigned int)cli->fnum ));
770
771         /*
772          * Send the last (or only) fragment of an RPC request. For small
773          * amounts of data (about 1024 bytes or so) the RPC request and response
774          * appears in a SMBtrans request and response.
775          */
776
777         if (!cli_api_pipe(cli->cli, "\\PIPE\\",
778                   setup, 2, 0,                     /* Setup, length, max */
779                   NULL, 0, 0,                      /* Params, length, max */
780                   pdata, data_len, max_data,       /* data, length, max */
781                   &rparam, &rparam_len,            /* return params, len */
782                   &prdata, &rdata_len))            /* return data, len */
783         {
784                 DEBUG(0, ("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x "
785                         "returned critical error. Error was %s\n",
786                         cli->desthost,
787                         cli->pipe_name,
788                         (unsigned int)cli->fnum,
789                         cli_errstr(cli->cli)));
790                 ret = cli_get_nt_error(cli->cli);
791                 SAFE_FREE(rparam);
792                 SAFE_FREE(prdata);
793                 goto err;
794         }
795
796         /* Throw away returned params - we know we won't use them. */
797
798         SAFE_FREE(rparam);
799
800         if (prdata == NULL) {
801                 DEBUG(3,("rpc_api_pipe: Remote machine %s pipe %s "
802                         "fnum 0x%x failed to return data.\n",
803                         cli->desthost,
804                         cli->pipe_name,
805                         (unsigned int)cli->fnum));
806                 /* Yes - some calls can truely return no data... */
807                 prs_mem_free(&current_pdu);
808                 return NT_STATUS_OK;
809         }
810
811         /*
812          * Give this memory as dynamic to the current pdu.
813          */
814
815         prs_give_memory(&current_pdu, prdata, rdata_len, True);
816
817         /* Ensure we can mess with the return prs_struct. */
818         SMB_ASSERT(UNMARSHALLING(rbuf));
819         SMB_ASSERT(prs_data_size(rbuf) == 0);
820
821         /* Make rbuf dynamic with no memory. */
822         prs_give_memory(rbuf, 0, 0, True);
823
824         while(1) {
825                 RPC_HDR rhdr;
826                 char *ret_data;
827                 uint32 ret_data_len;
828
829                 /* Ensure we have enough data for a pdu. */
830                 ret = cli_pipe_get_current_pdu(cli, &rhdr, &current_pdu);
831                 if (!NT_STATUS_IS_OK(ret)) {
832                         goto err;
833                 }
834
835                 /* We pass in rbuf here so if the alloc hint is set correctly 
836                    we can set the output size and avoid reallocs. */
837
838                 ret = cli_pipe_validate_current_pdu(cli, &rhdr, &current_pdu, expected_pkt_type,
839                                 &ret_data, &ret_data_len, rbuf);
840
841                 DEBUG(10,("rpc_api_pipe: got PDU len of %u at offset %u\n",
842                         prs_data_size(&current_pdu), current_rbuf_offset ));
843
844                 if (!NT_STATUS_IS_OK(ret)) {
845                         goto err;
846                 }
847
848                 if ((rhdr.flags & RPC_FLG_FIRST)) {
849                         if (rhdr.pack_type[0] == 0) {
850                                 /* Set the data type correctly for big-endian data on the first packet. */
851                                 DEBUG(10,("rpc_api_pipe: On machine %s pipe %s fnum 0x%x "
852                                         "PDU data format is big-endian.\n",
853                                         cli->desthost,
854                                         cli->pipe_name,
855                                         (unsigned int)cli->fnum));
856
857                                 prs_set_endian_data(rbuf, RPC_BIG_ENDIAN);
858                         } else {
859                                 /* Check endianness on subsequent packets. */
860                                 if (current_pdu.bigendian_data != rbuf->bigendian_data) {
861                                         DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to %s\n",
862                                                 rbuf->bigendian_data ? "big" : "little",
863                                                 current_pdu.bigendian_data ? "big" : "little" ));
864                                         ret = NT_STATUS_INVALID_PARAMETER;
865                                         goto err;
866                                 }
867                         }
868                 }
869
870                 /* Now copy the data portion out of the pdu into rbuf. */
871                 if (!prs_force_grow(rbuf, ret_data_len)) {
872                         ret = NT_STATUS_NO_MEMORY;
873                         goto err;
874                 }
875                 memcpy(prs_data_p(rbuf)+current_rbuf_offset, ret_data, (size_t)ret_data_len);
876                 current_rbuf_offset += ret_data_len;
877
878                 /* See if we've finished with all the data in current_pdu yet ? */
879                 ret = cli_pipe_reset_current_pdu(cli, &rhdr, &current_pdu);
880                 if (!NT_STATUS_IS_OK(ret)) {
881                         goto err;
882                 }
883
884                 if (rhdr.flags & RPC_FLG_LAST) {
885                         break; /* We're done. */
886                 }
887         }
888
889         DEBUG(10,("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x returned %u bytes.\n",
890                 cli->desthost,
891                 cli->pipe_name,
892                 (unsigned int)cli->fnum,
893                 (unsigned int)prs_data_size(rbuf) ));
894
895         prs_mem_free(&current_pdu);
896         return NT_STATUS_OK;
897
898   err:
899
900         prs_mem_free(&current_pdu);
901         prs_mem_free(rbuf);
902         return ret;
903 }
904
905 /*******************************************************************
906  Creates krb5 auth bind.
907  ********************************************************************/
908
909 static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
910                                                 enum pipe_auth_level auth_level,
911                                                 RPC_HDR_AUTH *pauth_out,
912                                                 prs_struct *auth_data)
913 {
914 #ifdef HAVE_KRB5
915         int ret;
916         struct kerberos_auth_struct *a = cli->auth.a_u.kerberos_auth;
917         DATA_BLOB tkt = data_blob_null;
918         DATA_BLOB tkt_wrapped = data_blob_null;
919
920         /* We may change the pad length before marshalling. */
921         init_rpc_hdr_auth(pauth_out, RPC_KRB5_AUTH_TYPE, (int)auth_level, 0, 1);
922
923         DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
924                 a->service_principal ));
925
926         /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
927
928         ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
929                         &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL);
930
931         if (ret) {
932                 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
933                         "failed with %s\n",
934                         a->service_principal,
935                         error_message(ret) ));
936
937                 data_blob_free(&tkt);
938                 prs_mem_free(auth_data);
939                 return NT_STATUS_INVALID_PARAMETER;
940         }
941
942         /* wrap that up in a nice GSS-API wrapping */
943         tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
944
945         data_blob_free(&tkt);
946
947         /* Auth len in the rpc header doesn't include auth_header. */
948         if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) {
949                 data_blob_free(&tkt_wrapped);
950                 prs_mem_free(auth_data);
951                 return NT_STATUS_NO_MEMORY;
952         }
953
954         DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
955         dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
956
957         data_blob_free(&tkt_wrapped);
958         return NT_STATUS_OK;
959 #else
960         return NT_STATUS_INVALID_PARAMETER;
961 #endif
962 }
963
964 /*******************************************************************
965  Creates SPNEGO NTLMSSP auth bind.
966  ********************************************************************/
967
968 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
969                                                 enum pipe_auth_level auth_level,
970                                                 RPC_HDR_AUTH *pauth_out,
971                                                 prs_struct *auth_data)
972 {
973         NTSTATUS nt_status;
974         DATA_BLOB null_blob = data_blob_null;
975         DATA_BLOB request = data_blob_null;
976         DATA_BLOB spnego_msg = data_blob_null;
977
978         /* We may change the pad length before marshalling. */
979         init_rpc_hdr_auth(pauth_out, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
980
981         DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
982         nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
983                                         null_blob,
984                                         &request);
985
986         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
987                 data_blob_free(&request);
988                 prs_mem_free(auth_data);
989                 return nt_status;
990         }
991
992         /* Wrap this in SPNEGO. */
993         spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
994
995         data_blob_free(&request);
996
997         /* Auth len in the rpc header doesn't include auth_header. */
998         if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) {
999                 data_blob_free(&spnego_msg);
1000                 prs_mem_free(auth_data);
1001                 return NT_STATUS_NO_MEMORY;
1002         }
1003
1004         DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1005         dump_data(5, spnego_msg.data, spnego_msg.length);
1006
1007         data_blob_free(&spnego_msg);
1008         return NT_STATUS_OK;
1009 }
1010
1011 /*******************************************************************
1012  Creates NTLMSSP auth bind.
1013  ********************************************************************/
1014
1015 static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1016                                                 enum pipe_auth_level auth_level,
1017                                                 RPC_HDR_AUTH *pauth_out,
1018                                                 prs_struct *auth_data)
1019 {
1020         NTSTATUS nt_status;
1021         DATA_BLOB null_blob = data_blob_null;
1022         DATA_BLOB request = data_blob_null;
1023
1024         /* We may change the pad length before marshalling. */
1025         init_rpc_hdr_auth(pauth_out, RPC_NTLMSSP_AUTH_TYPE, (int)auth_level, 0, 1);
1026
1027         DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1028         nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
1029                                         null_blob,
1030                                         &request);
1031
1032         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1033                 data_blob_free(&request);
1034                 prs_mem_free(auth_data);
1035                 return nt_status;
1036         }
1037
1038         /* Auth len in the rpc header doesn't include auth_header. */
1039         if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) {
1040                 data_blob_free(&request);
1041                 prs_mem_free(auth_data);
1042                 return NT_STATUS_NO_MEMORY;
1043         }
1044
1045         DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1046         dump_data(5, request.data, request.length);
1047
1048         data_blob_free(&request);
1049         return NT_STATUS_OK;
1050 }
1051
1052 /*******************************************************************
1053  Creates schannel auth bind.
1054  ********************************************************************/
1055
1056 static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1057                                                 enum pipe_auth_level auth_level,
1058                                                 RPC_HDR_AUTH *pauth_out,
1059                                                 prs_struct *auth_data)
1060 {
1061         RPC_AUTH_SCHANNEL_NEG schannel_neg;
1062
1063         /* We may change the pad length before marshalling. */
1064         init_rpc_hdr_auth(pauth_out, RPC_SCHANNEL_AUTH_TYPE, (int)auth_level, 0, 1);
1065
1066         /* Use lp_workgroup() if domain not specified */
1067
1068         if (!cli->domain || !cli->domain[0]) {
1069                 cli->domain = lp_workgroup();
1070         }
1071
1072         init_rpc_auth_schannel_neg(&schannel_neg, cli->domain, global_myname());
1073
1074         /*
1075          * Now marshall the data into the auth parse_struct.
1076          */
1077
1078         if(!smb_io_rpc_auth_schannel_neg("schannel_neg",
1079                                        &schannel_neg, auth_data, 0)) {
1080                 DEBUG(0,("Failed to marshall RPC_AUTH_SCHANNEL_NEG.\n"));
1081                 prs_mem_free(auth_data);
1082                 return NT_STATUS_NO_MEMORY;
1083         }
1084
1085         return NT_STATUS_OK;
1086 }
1087
1088 /*******************************************************************
1089  Creates the internals of a DCE/RPC bind request or alter context PDU.
1090  ********************************************************************/
1091
1092 static NTSTATUS create_bind_or_alt_ctx_internal(enum RPC_PKT_TYPE pkt_type,
1093                                                 prs_struct *rpc_out, 
1094                                                 uint32 rpc_call_id,
1095                                                 const RPC_IFACE *abstract,
1096                                                 const RPC_IFACE *transfer,
1097                                                 RPC_HDR_AUTH *phdr_auth,
1098                                                 prs_struct *pauth_info)
1099 {
1100         RPC_HDR hdr;
1101         RPC_HDR_RB hdr_rb;
1102         RPC_CONTEXT rpc_ctx;
1103         uint16 auth_len = prs_offset(pauth_info);
1104         uint8 ss_padding_len = 0;
1105         uint16 frag_len = 0;
1106
1107         /* create the RPC context. */
1108         init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);
1109
1110         /* create the bind request RPC_HDR_RB */
1111         init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
1112
1113         /* Start building the frag length. */
1114         frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1115
1116         /* Do we need to pad ? */
1117         if (auth_len) {
1118                 uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1119                 if (data_len % 8) {
1120                         ss_padding_len = 8 - (data_len % 8);
1121                         phdr_auth->auth_pad_len = ss_padding_len;
1122                 }
1123                 frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;
1124         }
1125
1126         /* Create the request RPC_HDR */
1127         init_rpc_hdr(&hdr, pkt_type, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id, frag_len, auth_len);
1128
1129         /* Marshall the RPC header */
1130         if(!smb_io_rpc_hdr("hdr"   , &hdr, rpc_out, 0)) {
1131                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
1132                 return NT_STATUS_NO_MEMORY;
1133         }
1134
1135         /* Marshall the bind request data */
1136         if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
1137                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1138                 return NT_STATUS_NO_MEMORY;
1139         }
1140
1141         /*
1142          * Grow the outgoing buffer to store any auth info.
1143          */
1144
1145         if(auth_len != 0) {
1146                 if (ss_padding_len) {
1147                         char pad[8];
1148                         memset(pad, '\0', 8);
1149                         if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
1150                                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
1151                                 return NT_STATUS_NO_MEMORY;
1152                         }
1153                 }
1154
1155                 if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {
1156                         DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
1157                         return NT_STATUS_NO_MEMORY;
1158                 }
1159
1160
1161                 if(!prs_append_prs_data( rpc_out, pauth_info)) {
1162                         DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
1163                         return NT_STATUS_NO_MEMORY;
1164                 }
1165         }
1166
1167         return NT_STATUS_OK;
1168 }
1169
1170 /*******************************************************************
1171  Creates a DCE/RPC bind request.
1172  ********************************************************************/
1173
1174 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1175                                 prs_struct *rpc_out, 
1176                                 uint32 rpc_call_id,
1177                                 const RPC_IFACE *abstract,
1178                                 const RPC_IFACE *transfer,
1179                                 enum pipe_auth_type auth_type,
1180                                 enum pipe_auth_level auth_level)
1181 {
1182         RPC_HDR_AUTH hdr_auth;
1183         prs_struct auth_info;
1184         NTSTATUS ret = NT_STATUS_OK;
1185
1186         ZERO_STRUCT(hdr_auth);
1187         if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
1188                 return NT_STATUS_NO_MEMORY;
1189
1190         switch (auth_type) {
1191                 case PIPE_AUTH_TYPE_SCHANNEL:
1192                         ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1193                         if (!NT_STATUS_IS_OK(ret)) {
1194                                 prs_mem_free(&auth_info);
1195                                 return ret;
1196                         }
1197                         break;
1198
1199                 case PIPE_AUTH_TYPE_NTLMSSP:
1200                         ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1201                         if (!NT_STATUS_IS_OK(ret)) {
1202                                 prs_mem_free(&auth_info);
1203                                 return ret;
1204                         }
1205                         break;
1206
1207                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1208                         ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1209                         if (!NT_STATUS_IS_OK(ret)) {
1210                                 prs_mem_free(&auth_info);
1211                                 return ret;
1212                         }
1213                         break;
1214
1215                 case PIPE_AUTH_TYPE_KRB5:
1216                         ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1217                         if (!NT_STATUS_IS_OK(ret)) {
1218                                 prs_mem_free(&auth_info);
1219                                 return ret;
1220                         }
1221                         break;
1222
1223                 case PIPE_AUTH_TYPE_NONE:
1224                         break;
1225
1226                 default:
1227                         /* "Can't" happen. */
1228                         return NT_STATUS_INVALID_INFO_CLASS;
1229         }
1230
1231         ret = create_bind_or_alt_ctx_internal(RPC_BIND,
1232                                                 rpc_out, 
1233                                                 rpc_call_id,
1234                                                 abstract,
1235                                                 transfer,
1236                                                 &hdr_auth,
1237                                                 &auth_info);
1238
1239         prs_mem_free(&auth_info);
1240         return ret;
1241 }
1242
1243 /*******************************************************************
1244  Create and add the NTLMSSP sign/seal auth header and data.
1245  ********************************************************************/
1246
1247 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1248                                         RPC_HDR *phdr,
1249                                         uint32 ss_padding_len,
1250                                         prs_struct *outgoing_pdu)
1251 {
1252         RPC_HDR_AUTH auth_info;
1253         NTSTATUS status;
1254         DATA_BLOB auth_blob = data_blob_null;
1255         uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1256
1257         if (!cli->auth.a_u.ntlmssp_state) {
1258                 return NT_STATUS_INVALID_PARAMETER;
1259         }
1260
1261         /* Init and marshall the auth header. */
1262         init_rpc_hdr_auth(&auth_info,
1263                         map_pipe_auth_type_to_rpc_auth_type(cli->auth.auth_type),
1264                         cli->auth.auth_level,
1265                         ss_padding_len,
1266                         1 /* context id. */);
1267
1268         if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1269                 DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1270                 data_blob_free(&auth_blob);
1271                 return NT_STATUS_NO_MEMORY;
1272         }
1273
1274         switch (cli->auth.auth_level) {
1275                 case PIPE_AUTH_LEVEL_PRIVACY:
1276                         /* Data portion is encrypted. */
1277                         status = ntlmssp_seal_packet(cli->auth.a_u.ntlmssp_state,
1278                                         (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1279                                         data_and_pad_len,
1280                                         (unsigned char *)prs_data_p(outgoing_pdu),
1281                                         (size_t)prs_offset(outgoing_pdu),
1282                                         &auth_blob);
1283                         if (!NT_STATUS_IS_OK(status)) {
1284                                 data_blob_free(&auth_blob);
1285                                 return status;
1286                         }
1287                         break;
1288
1289                 case PIPE_AUTH_LEVEL_INTEGRITY:
1290                         /* Data is signed. */
1291                         status = ntlmssp_sign_packet(cli->auth.a_u.ntlmssp_state,
1292                                         (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
1293                                         data_and_pad_len,
1294                                         (unsigned char *)prs_data_p(outgoing_pdu),
1295                                         (size_t)prs_offset(outgoing_pdu),
1296                                         &auth_blob);
1297                         if (!NT_STATUS_IS_OK(status)) {
1298                                 data_blob_free(&auth_blob);
1299                                 return status;
1300                         }
1301                         break;
1302
1303                 default:
1304                         /* Can't happen. */
1305                         smb_panic("bad auth level");
1306                         /* Notreached. */
1307                         return NT_STATUS_INVALID_PARAMETER;
1308         }
1309
1310         /* Finally marshall the blob. */
1311                                                                                                        
1312         if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) {
1313                 DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
1314                         (unsigned int)NTLMSSP_SIG_SIZE));
1315                 data_blob_free(&auth_blob);
1316                 return NT_STATUS_NO_MEMORY;
1317         }
1318                                                                                                                                 
1319         data_blob_free(&auth_blob);
1320         return NT_STATUS_OK;
1321 }
1322
1323 /*******************************************************************
1324  Create and add the schannel sign/seal auth header and data.
1325  ********************************************************************/
1326
1327 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
1328                                         RPC_HDR *phdr,
1329                                         uint32 ss_padding_len,
1330                                         prs_struct *outgoing_pdu)
1331 {
1332         RPC_HDR_AUTH auth_info;
1333         RPC_AUTH_SCHANNEL_CHK verf;
1334         struct schannel_auth_struct *sas = cli->auth.a_u.schannel_auth;
1335         char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
1336         size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1337
1338         if (!sas) {
1339                 return NT_STATUS_INVALID_PARAMETER;
1340         }
1341
1342         /* Init and marshall the auth header. */
1343         init_rpc_hdr_auth(&auth_info,
1344                         map_pipe_auth_type_to_rpc_auth_type(cli->auth.auth_type),
1345                         cli->auth.auth_level,
1346                         ss_padding_len,
1347                         1 /* context id. */);
1348
1349         if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1350                 DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1351                 return NT_STATUS_NO_MEMORY;
1352         }
1353
1354         switch (cli->auth.auth_level) {
1355                 case PIPE_AUTH_LEVEL_PRIVACY:
1356                 case PIPE_AUTH_LEVEL_INTEGRITY:
1357                         DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
1358                                 sas->seq_num));
1359
1360                         schannel_encode(sas,
1361                                         cli->auth.auth_level,
1362                                         SENDER_IS_INITIATOR,
1363                                         &verf,
1364                                         data_p,
1365                                         data_and_pad_len);
1366
1367                         sas->seq_num++;
1368                         break;
1369
1370                 default:
1371                         /* Can't happen. */
1372                         smb_panic("bad auth level");
1373                         /* Notreached. */
1374                         return NT_STATUS_INVALID_PARAMETER;
1375         }
1376
1377         /* Finally marshall the blob. */
1378         smb_io_rpc_auth_schannel_chk("",
1379                         RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
1380                         &verf,
1381                         outgoing_pdu,
1382                         0);
1383                                                                                                
1384         return NT_STATUS_OK;
1385 }
1386
1387 /*******************************************************************
1388  Calculate how much data we're going to send in this packet, also
1389  work out any sign/seal padding length.
1390  ********************************************************************/
1391
1392 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
1393                                         uint32 data_left,
1394                                         uint16 *p_frag_len,
1395                                         uint16 *p_auth_len,
1396                                         uint32 *p_ss_padding)
1397 {
1398         uint32 data_space, data_len;
1399
1400         switch (cli->auth.auth_level) {
1401                 case PIPE_AUTH_LEVEL_NONE:
1402                 case PIPE_AUTH_LEVEL_CONNECT:
1403                         data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
1404                         data_len = MIN(data_space, data_left);
1405                         *p_ss_padding = 0;
1406                         *p_auth_len = 0;
1407                         *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
1408                         return data_len;
1409
1410                 case PIPE_AUTH_LEVEL_INTEGRITY:
1411                 case PIPE_AUTH_LEVEL_PRIVACY:
1412                         /* Treat the same for all authenticated rpc requests. */
1413                         switch(cli->auth.auth_type) {
1414                                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1415                                 case PIPE_AUTH_TYPE_NTLMSSP:
1416                                         *p_auth_len = NTLMSSP_SIG_SIZE;
1417                                         break;
1418                                 case PIPE_AUTH_TYPE_SCHANNEL:
1419                                         *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
1420                                         break;
1421                                 default:
1422                                         smb_panic("bad auth type");
1423                                         break;
1424                         }
1425
1426                         data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
1427                                                 RPC_HDR_AUTH_LEN - *p_auth_len;
1428
1429                         data_len = MIN(data_space, data_left);
1430                         if (data_len % 8) {
1431                                 *p_ss_padding = 8 - (data_len % 8);
1432                         }
1433                         *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN +                /* Normal headers. */
1434                                         data_len + *p_ss_padding +              /* data plus padding. */
1435                                         RPC_HDR_AUTH_LEN + *p_auth_len;         /* Auth header and auth data. */
1436                         return data_len;
1437
1438                 default:
1439                         smb_panic("bad auth level");
1440                         /* Notreached. */
1441                         return 0;
1442         }
1443 }
1444
1445 /*******************************************************************
1446  External interface.
1447  Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1448  Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1449  and deals with signing/sealing details.
1450  ********************************************************************/
1451
1452 NTSTATUS rpc_api_pipe_req(struct rpc_pipe_client *cli,
1453                         uint8 op_num,
1454                         prs_struct *in_data,
1455                         prs_struct *out_data)
1456 {
1457         NTSTATUS ret;
1458         uint32 data_left = prs_offset(in_data);
1459         uint32 alloc_hint = prs_offset(in_data);
1460         uint32 data_sent_thistime = 0;
1461         uint32 current_data_offset = 0;
1462         uint32 call_id = get_rpc_call_id();
1463         char pad[8];
1464         prs_struct outgoing_pdu;
1465
1466         memset(pad, '\0', 8);
1467
1468         if (cli->max_xmit_frag < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
1469                 /* Server is screwed up ! */
1470                 return NT_STATUS_INVALID_PARAMETER;
1471         }
1472
1473         if (!prs_init(&outgoing_pdu, cli->max_xmit_frag, prs_get_mem_context(in_data), MARSHALL))
1474                 return NT_STATUS_NO_MEMORY;
1475
1476         while (1) {
1477                 RPC_HDR hdr;
1478                 RPC_HDR_REQ hdr_req;
1479                 uint16 auth_len = 0;
1480                 uint16 frag_len = 0;
1481                 uint8 flags = 0;
1482                 uint32 ss_padding = 0;
1483
1484                 data_sent_thistime = calculate_data_len_tosend(cli, data_left,
1485                                                 &frag_len, &auth_len, &ss_padding);
1486
1487                 if (current_data_offset == 0) {
1488                         flags = RPC_FLG_FIRST;
1489                 }
1490
1491                 if (data_sent_thistime == data_left) {
1492                         flags |= RPC_FLG_LAST;
1493                 }
1494
1495                 /* Create and marshall the header and request header. */
1496                 init_rpc_hdr(&hdr, RPC_REQUEST, flags, call_id, frag_len, auth_len);
1497
1498                 if(!smb_io_rpc_hdr("hdr    ", &hdr, &outgoing_pdu, 0)) {
1499                         prs_mem_free(&outgoing_pdu);
1500                         return NT_STATUS_NO_MEMORY;
1501                 }
1502
1503                 /* Create the rpc request RPC_HDR_REQ */
1504                 init_rpc_hdr_req(&hdr_req, alloc_hint, op_num);
1505
1506                 if(!smb_io_rpc_hdr_req("hdr_req", &hdr_req, &outgoing_pdu, 0)) {
1507                         prs_mem_free(&outgoing_pdu);
1508                         return NT_STATUS_NO_MEMORY;
1509                 }
1510
1511                 /* Copy in the data, plus any ss padding. */
1512                 if (!prs_append_some_prs_data(&outgoing_pdu, in_data, current_data_offset, data_sent_thistime)) {
1513                         prs_mem_free(&outgoing_pdu);
1514                         return NT_STATUS_NO_MEMORY;
1515                 }
1516
1517                 /* Copy the sign/seal padding data. */
1518                 if (ss_padding) {
1519                         if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding)) {
1520                                 prs_mem_free(&outgoing_pdu);
1521                                 return NT_STATUS_NO_MEMORY;
1522                         }
1523                 }
1524
1525                 /* Generate any auth sign/seal and add the auth footer. */
1526                 if (auth_len) {
1527                         switch (cli->auth.auth_type) {
1528                                 case PIPE_AUTH_TYPE_NONE:
1529                                         break;
1530                                 case PIPE_AUTH_TYPE_NTLMSSP:
1531                                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1532                                         ret = add_ntlmssp_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
1533                                         if (!NT_STATUS_IS_OK(ret)) {
1534                                                 prs_mem_free(&outgoing_pdu);
1535                                                 return ret;
1536                                         }
1537                                         break;
1538                                 case PIPE_AUTH_TYPE_SCHANNEL:
1539                                         ret = add_schannel_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
1540                                         if (!NT_STATUS_IS_OK(ret)) {
1541                                                 prs_mem_free(&outgoing_pdu);
1542                                                 return ret;
1543                                         }
1544                                         break;
1545                                 default:
1546                                         smb_panic("bad auth type");
1547                                         break; /* notreached */
1548                         }
1549                 }
1550
1551                 /* Actually send the packet. */
1552                 if (flags & RPC_FLG_LAST) {
1553                         /* Last packet - send the data, get the reply and return. */
1554                         ret = rpc_api_pipe(cli, &outgoing_pdu, out_data, RPC_RESPONSE);
1555                         prs_mem_free(&outgoing_pdu);
1556
1557                         if (DEBUGLEVEL >= 50) {
1558                                 char *dump_name = NULL;
1559                                 /* Also capture received data */
1560                                 if (asprintf(&dump_name, "%s/reply_%s_%d",
1561                                                 get_dyn_LOGFILEBASE(), cli->pipe_name,
1562                                                 op_num) > 0) {
1563                                         prs_dump(dump_name, op_num, out_data);
1564                                         SAFE_FREE(dump_name);
1565                                 }
1566                         }
1567
1568                         return ret;
1569                 } else {
1570                         /* More packets to come - write and continue. */
1571                         ssize_t num_written = cli_write(cli->cli, cli->fnum, 8, /* 8 means message mode. */
1572                                                         prs_data_p(&outgoing_pdu),
1573                                                         (off_t)0,
1574                                                         (size_t)hdr.frag_len);
1575
1576                         if (num_written != hdr.frag_len) {
1577                                 prs_mem_free(&outgoing_pdu);
1578                                 return cli_get_nt_error(cli->cli);
1579                         }
1580                 }
1581
1582                 current_data_offset += data_sent_thistime;
1583                 data_left -= data_sent_thistime;
1584
1585                 /* Reset the marshalling position back to zero. */
1586                 if (!prs_set_offset(&outgoing_pdu, 0)) {
1587                         prs_mem_free(&outgoing_pdu);
1588                         return NT_STATUS_NO_MEMORY;
1589                 }
1590         }
1591 }
1592 #if 0
1593 /****************************************************************************
1594  Set the handle state.
1595 ****************************************************************************/
1596
1597 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
1598                                    const char *pipe_name, uint16 device_state)
1599 {
1600         bool state_set = False;
1601         char param[2];
1602         uint16 setup[2]; /* only need 2 uint16 setup parameters */
1603         char *rparam = NULL;
1604         char *rdata = NULL;
1605         uint32 rparam_len, rdata_len;
1606
1607         if (pipe_name == NULL)
1608                 return False;
1609
1610         DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
1611                  cli->fnum, pipe_name, device_state));
1612
1613         /* create parameters: device state */
1614         SSVAL(param, 0, device_state);
1615
1616         /* create setup parameters. */
1617         setup[0] = 0x0001; 
1618         setup[1] = cli->fnum; /* pipe file handle.  got this from an SMBOpenX. */
1619
1620         /* send the data on \PIPE\ */
1621         if (cli_api_pipe(cli->cli, "\\PIPE\\",
1622                     setup, 2, 0,                /* setup, length, max */
1623                     param, 2, 0,                /* param, length, max */
1624                     NULL, 0, 1024,              /* data, length, max */
1625                     &rparam, &rparam_len,        /* return param, length */
1626                     &rdata, &rdata_len))         /* return data, length */
1627         {
1628                 DEBUG(5, ("Set Handle state: return OK\n"));
1629                 state_set = True;
1630         }
1631
1632         SAFE_FREE(rparam);
1633         SAFE_FREE(rdata);
1634
1635         return state_set;
1636 }
1637 #endif
1638
1639 /****************************************************************************
1640  Check the rpc bind acknowledge response.
1641 ****************************************************************************/
1642
1643 static bool check_bind_response(RPC_HDR_BA *hdr_ba, const RPC_IFACE *transfer)
1644 {
1645         if ( hdr_ba->addr.len == 0) {
1646                 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1647         }
1648
1649         /* check the transfer syntax */
1650         if ((hdr_ba->transfer.if_version != transfer->if_version) ||
1651              (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1652                 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1653                 return False;
1654         }
1655
1656         if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {
1657                 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1658                           hdr_ba->res.num_results, hdr_ba->res.reason));
1659         }
1660
1661         DEBUG(5,("check_bind_response: accepted!\n"));
1662         return True;
1663 }
1664
1665 /*******************************************************************
1666  Creates a DCE/RPC bind authentication response.
1667  This is the packet that is sent back to the server once we
1668  have received a BIND-ACK, to finish the third leg of
1669  the authentication handshake.
1670  ********************************************************************/
1671
1672 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
1673                                 uint32 rpc_call_id,
1674                                 enum pipe_auth_type auth_type,
1675                                 enum pipe_auth_level auth_level,
1676                                 DATA_BLOB *pauth_blob,
1677                                 prs_struct *rpc_out)
1678 {
1679         RPC_HDR hdr;
1680         RPC_HDR_AUTH hdr_auth;
1681         uint32 pad = 0;
1682
1683         /* Create the request RPC_HDR */
1684         init_rpc_hdr(&hdr, RPC_AUTH3, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id,
1685                      RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,
1686                      pauth_blob->length );
1687         
1688         /* Marshall it. */
1689         if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
1690                 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
1691                 return NT_STATUS_NO_MEMORY;
1692         }
1693
1694         /*
1695                 I'm puzzled about this - seems to violate the DCE RPC auth rules,
1696                 about padding - shouldn't this pad to length 8 ? JRA.
1697         */
1698
1699         /* 4 bytes padding. */
1700         if (!prs_uint32("pad", rpc_out, 0, &pad)) {
1701                 DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
1702                 return NT_STATUS_NO_MEMORY;
1703         }
1704
1705         /* Create the request RPC_HDR_AUTHA */
1706         init_rpc_hdr_auth(&hdr_auth,
1707                         map_pipe_auth_type_to_rpc_auth_type(auth_type),
1708                         auth_level, 0, 1);
1709
1710         if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {
1711                 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
1712                 return NT_STATUS_NO_MEMORY;
1713         }
1714
1715         /*
1716          * Append the auth data to the outgoing buffer.
1717          */
1718
1719         if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {
1720                 DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
1721                 return NT_STATUS_NO_MEMORY;
1722         }
1723
1724         return NT_STATUS_OK;
1725 }
1726
1727 /****************************************************************************
1728  Create and send the third packet in an RPC auth.
1729 ****************************************************************************/
1730
1731 static NTSTATUS rpc_finish_auth3_bind(struct rpc_pipe_client *cli,
1732                                 RPC_HDR *phdr,
1733                                 prs_struct *rbuf,
1734                                 uint32 rpc_call_id,
1735                                 enum pipe_auth_type auth_type,
1736                                 enum pipe_auth_level auth_level)
1737 {
1738         DATA_BLOB server_response = data_blob_null;
1739         DATA_BLOB client_reply = data_blob_null;
1740         RPC_HDR_AUTH hdr_auth;
1741         NTSTATUS nt_status;
1742         prs_struct rpc_out;
1743         ssize_t ret;
1744
1745         if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
1746                 return NT_STATUS_INVALID_PARAMETER;
1747         }
1748
1749         /* Process the returned NTLMSSP blob first. */
1750         if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
1751                 return NT_STATUS_INVALID_PARAMETER;
1752         }
1753
1754         if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
1755                 return NT_STATUS_INVALID_PARAMETER;
1756         }
1757
1758         /* TODO - check auth_type/auth_level match. */
1759
1760         server_response = data_blob(NULL, phdr->auth_len);
1761         prs_copy_data_out((char *)server_response.data, rbuf, phdr->auth_len);
1762         
1763         nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
1764                                    server_response,
1765                                    &client_reply);
1766         
1767         if (!NT_STATUS_IS_OK(nt_status)) {
1768                 DEBUG(0,("rpc_finish_auth3_bind: NTLMSSP update using server blob failed.\n"));
1769                 data_blob_free(&server_response);
1770                 return nt_status;
1771         }
1772
1773         prs_init_empty(&rpc_out, prs_get_mem_context(rbuf), MARSHALL);
1774
1775         nt_status = create_rpc_bind_auth3(cli, rpc_call_id,
1776                                 auth_type, auth_level,
1777                                 &client_reply, &rpc_out);
1778
1779         if (!NT_STATUS_IS_OK(nt_status)) {
1780                 prs_mem_free(&rpc_out);
1781                 data_blob_free(&client_reply);
1782                 data_blob_free(&server_response);
1783                 return nt_status;
1784         }
1785
1786         /* 8 here is named pipe message mode. */
1787         ret = cli_write(cli->cli, cli->fnum, 0x8, prs_data_p(&rpc_out), 0,
1788                                 (size_t)prs_offset(&rpc_out));
1789
1790         if (ret != (ssize_t)prs_offset(&rpc_out)) {
1791                 DEBUG(0,("rpc_send_auth_auth3: cli_write failed. Return was %d\n", (int)ret));
1792                 prs_mem_free(&rpc_out);
1793                 data_blob_free(&client_reply);
1794                 data_blob_free(&server_response);
1795                 return cli_get_nt_error(cli->cli);
1796         }
1797
1798         DEBUG(5,("rpc_send_auth_auth3: Remote machine %s pipe %s "
1799                 "fnum 0x%x sent auth3 response ok.\n",
1800                 cli->desthost,
1801                 cli->pipe_name,
1802                 (unsigned int)cli->fnum));
1803
1804         prs_mem_free(&rpc_out);
1805         data_blob_free(&client_reply);
1806         data_blob_free(&server_response);
1807         return NT_STATUS_OK;
1808 }
1809
1810 /*******************************************************************
1811  Creates a DCE/RPC bind alter context authentication request which
1812  may contain a spnego auth blobl
1813  ********************************************************************/
1814
1815 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
1816                                         const RPC_IFACE *abstract,
1817                                         const RPC_IFACE *transfer,
1818                                         enum pipe_auth_level auth_level,
1819                                         const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1820                                         prs_struct *rpc_out)
1821 {
1822         RPC_HDR_AUTH hdr_auth;
1823         prs_struct auth_info;
1824         NTSTATUS ret = NT_STATUS_OK;
1825
1826         ZERO_STRUCT(hdr_auth);
1827         if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
1828                 return NT_STATUS_NO_MEMORY;
1829
1830         /* We may change the pad length before marshalling. */
1831         init_rpc_hdr_auth(&hdr_auth, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
1832
1833         if (pauth_blob->length) {
1834                 if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {
1835                         prs_mem_free(&auth_info);
1836                         return NT_STATUS_NO_MEMORY;
1837                 }
1838         }
1839
1840         ret = create_bind_or_alt_ctx_internal(RPC_ALTCONT,
1841                                                 rpc_out, 
1842                                                 rpc_call_id,
1843                                                 abstract,
1844                                                 transfer,
1845                                                 &hdr_auth,
1846                                                 &auth_info);
1847         prs_mem_free(&auth_info);
1848         return ret;
1849 }
1850
1851 /*******************************************************************
1852  Third leg of the SPNEGO bind mechanism - sends alter context PDU
1853  and gets a response.
1854  ********************************************************************/
1855
1856 static NTSTATUS rpc_finish_spnego_ntlmssp_bind(struct rpc_pipe_client *cli,
1857                                 RPC_HDR *phdr,
1858                                 prs_struct *rbuf,
1859                                 uint32 rpc_call_id,
1860                                 const RPC_IFACE *abstract,
1861                                 const RPC_IFACE *transfer,
1862                                 enum pipe_auth_type auth_type,
1863                                 enum pipe_auth_level auth_level)
1864 {
1865         DATA_BLOB server_spnego_response = data_blob_null;
1866         DATA_BLOB server_ntlm_response = data_blob_null;
1867         DATA_BLOB client_reply = data_blob_null;
1868         DATA_BLOB tmp_blob = data_blob_null;
1869         RPC_HDR_AUTH hdr_auth;
1870         NTSTATUS nt_status;
1871         prs_struct rpc_out;
1872
1873         if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
1874                 return NT_STATUS_INVALID_PARAMETER;
1875         }
1876
1877         /* Process the returned NTLMSSP blob first. */
1878         if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
1879                 return NT_STATUS_INVALID_PARAMETER;
1880         }
1881
1882         if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
1883                 return NT_STATUS_INVALID_PARAMETER;
1884         }
1885
1886         server_spnego_response = data_blob(NULL, phdr->auth_len);
1887         prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
1888         
1889         /* The server might give us back two challenges - tmp_blob is for the second. */
1890         if (!spnego_parse_challenge(server_spnego_response, &server_ntlm_response, &tmp_blob)) {
1891                 data_blob_free(&server_spnego_response);
1892                 data_blob_free(&server_ntlm_response);
1893                 data_blob_free(&tmp_blob);
1894                 return NT_STATUS_INVALID_PARAMETER;
1895         }
1896
1897         /* We're finished with the server spnego response and the tmp_blob. */
1898         data_blob_free(&server_spnego_response);
1899         data_blob_free(&tmp_blob);
1900
1901         nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
1902                                    server_ntlm_response,
1903                                    &client_reply);
1904         
1905         /* Finished with the server_ntlm response */
1906         data_blob_free(&server_ntlm_response);
1907
1908         if (!NT_STATUS_IS_OK(nt_status)) {
1909                 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update using server blob failed.\n"));
1910                 data_blob_free(&client_reply);
1911                 return nt_status;
1912         }
1913
1914         /* SPNEGO wrap the client reply. */
1915         tmp_blob = spnego_gen_auth(client_reply);
1916         data_blob_free(&client_reply);
1917         client_reply = tmp_blob;
1918         tmp_blob = data_blob_null; /* Ensure it's safe to free this just in case. */
1919
1920         /* Now prepare the alter context pdu. */
1921         prs_init_empty(&rpc_out, prs_get_mem_context(rbuf), MARSHALL);
1922
1923         nt_status = create_rpc_alter_context(rpc_call_id,
1924                                                 abstract,
1925                                                 transfer,
1926                                                 auth_level,
1927                                                 &client_reply,
1928                                                 &rpc_out);
1929
1930         data_blob_free(&client_reply);
1931
1932         if (!NT_STATUS_IS_OK(nt_status)) {
1933                 prs_mem_free(&rpc_out);
1934                 return nt_status;
1935         }
1936
1937         /* Initialize the returning data struct. */
1938         prs_mem_free(rbuf);
1939         prs_init_empty(rbuf, talloc_tos(), UNMARSHALL);
1940
1941         nt_status = rpc_api_pipe(cli, &rpc_out, rbuf, RPC_ALTCONTRESP);
1942         if (!NT_STATUS_IS_OK(nt_status)) {
1943                 prs_mem_free(&rpc_out);
1944                 return nt_status;
1945         }
1946
1947         prs_mem_free(&rpc_out);
1948
1949         /* Get the auth blob from the reply. */
1950         if(!smb_io_rpc_hdr("rpc_hdr   ", phdr, rbuf, 0)) {
1951                 DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: Failed to unmarshall RPC_HDR.\n"));
1952                 return NT_STATUS_BUFFER_TOO_SMALL;
1953         }
1954
1955         if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
1956                 return NT_STATUS_INVALID_PARAMETER;
1957         }
1958
1959         if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
1960                 return NT_STATUS_INVALID_PARAMETER;
1961         }
1962
1963         server_spnego_response = data_blob(NULL, phdr->auth_len);
1964         prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
1965
1966         /* Check we got a valid auth response. */
1967         if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK, OID_NTLMSSP, &tmp_blob)) {
1968                 data_blob_free(&server_spnego_response);
1969                 data_blob_free(&tmp_blob);
1970                 return NT_STATUS_INVALID_PARAMETER;
1971         }
1972
1973         data_blob_free(&server_spnego_response);
1974         data_blob_free(&tmp_blob);
1975
1976         DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
1977                 "remote machine %s pipe %s fnum 0x%x.\n",
1978                 cli->desthost,
1979                 cli->pipe_name,
1980                 (unsigned int)cli->fnum));
1981
1982         return NT_STATUS_OK;
1983 }
1984
1985 /****************************************************************************
1986  Do an rpc bind.
1987 ****************************************************************************/
1988
1989 static NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
1990                         enum pipe_auth_type auth_type,
1991                         enum pipe_auth_level auth_level)
1992 {
1993         RPC_HDR hdr;
1994         RPC_HDR_BA hdr_ba;
1995         prs_struct rpc_out;
1996         prs_struct rbuf;
1997         uint32 rpc_call_id;
1998         NTSTATUS status;
1999
2000         DEBUG(5,("Bind RPC Pipe[%x]: %s auth_type %u, auth_level %u\n",
2001                 (unsigned int)cli->fnum,
2002                 cli->pipe_name,
2003                 (unsigned int)auth_type,
2004                 (unsigned int)auth_level ));
2005
2006         prs_init_empty(&rpc_out, talloc_tos(), MARSHALL);
2007
2008         rpc_call_id = get_rpc_call_id();
2009
2010         /* Marshall the outgoing data. */
2011         status = create_rpc_bind_req(cli, &rpc_out, rpc_call_id,
2012                                 cli->abstract_syntax,
2013                                 cli->transfer_syntax,
2014                                 auth_type,
2015                                 auth_level);
2016
2017         if (!NT_STATUS_IS_OK(status)) {
2018                 prs_mem_free(&rpc_out);
2019                 return status;
2020         }
2021
2022         /* Initialize the incoming data struct. */
2023         prs_init_empty(&rbuf, talloc_tos(), UNMARSHALL);
2024
2025         /* send data on \PIPE\.  receive a response */
2026         status = rpc_api_pipe(cli, &rpc_out, &rbuf, RPC_BINDACK);
2027         if (!NT_STATUS_IS_OK(status)) {
2028                 prs_mem_free(&rpc_out);
2029                 return status;
2030         }
2031
2032         prs_mem_free(&rpc_out);
2033
2034         DEBUG(3,("rpc_pipe_bind: Remote machine %s pipe %s "
2035                 "fnum 0x%x bind request returned ok.\n",
2036                 cli->desthost,
2037                 cli->pipe_name,
2038                 (unsigned int)cli->fnum));
2039
2040         /* Unmarshall the RPC header */
2041         if(!smb_io_rpc_hdr("hdr"   , &hdr, &rbuf, 0)) {
2042                 DEBUG(0,("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
2043                 prs_mem_free(&rbuf);
2044                 return NT_STATUS_BUFFER_TOO_SMALL;
2045         }
2046
2047         if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rbuf, 0)) {
2048                 DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n"));
2049                 prs_mem_free(&rbuf);
2050                 return NT_STATUS_BUFFER_TOO_SMALL;
2051         }
2052
2053         if(!check_bind_response(&hdr_ba, cli->transfer_syntax)) {
2054                 DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n"));
2055                 prs_mem_free(&rbuf);
2056                 return NT_STATUS_BUFFER_TOO_SMALL;
2057         }
2058
2059         cli->max_xmit_frag = hdr_ba.bba.max_tsize;
2060         cli->max_recv_frag = hdr_ba.bba.max_rsize;
2061
2062         /* For authenticated binds we may need to do 3 or 4 leg binds. */
2063         switch(auth_type) {
2064
2065                 case PIPE_AUTH_TYPE_NONE:
2066                 case PIPE_AUTH_TYPE_SCHANNEL:
2067                         /* Bind complete. */
2068                         break;
2069
2070                 case PIPE_AUTH_TYPE_NTLMSSP:
2071                         /* Need to send AUTH3 packet - no reply. */
2072                         status = rpc_finish_auth3_bind(cli, &hdr, &rbuf, rpc_call_id,
2073                                                 auth_type, auth_level);
2074                         if (!NT_STATUS_IS_OK(status)) {
2075                                 prs_mem_free(&rbuf);
2076                                 return status;
2077                         }
2078                         break;
2079
2080                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2081                         /* Need to send alter context request and reply. */
2082                         status = rpc_finish_spnego_ntlmssp_bind(cli, &hdr, &rbuf, rpc_call_id,
2083                                                 cli->abstract_syntax,
2084                                                 cli->transfer_syntax,
2085                                                 auth_type, auth_level);
2086                         if (!NT_STATUS_IS_OK(status)) {
2087                                 prs_mem_free(&rbuf);
2088                                 return status;
2089                         }
2090                         break;
2091
2092                 case PIPE_AUTH_TYPE_KRB5:
2093                         /* */
2094
2095                 default:
2096                         DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2097                                 (unsigned int)auth_type ));
2098                         prs_mem_free(&rbuf);
2099                         return NT_STATUS_INVALID_INFO_CLASS;
2100         }
2101
2102         /* For NTLMSSP ensure the server gave us the auth_level we wanted. */
2103         if (auth_type == PIPE_AUTH_TYPE_NTLMSSP || auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
2104                 if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2105                         if (!(cli->auth.a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
2106                                 DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP signing and server refused.\n"));
2107                                 prs_mem_free(&rbuf);
2108                                 return NT_STATUS_INVALID_PARAMETER;
2109                         }
2110                 }
2111                 if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2112                         if (!(cli->auth.a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
2113                                 DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP sealing and server refused.\n"));
2114                                 prs_mem_free(&rbuf);
2115                                 return NT_STATUS_INVALID_PARAMETER;
2116                         }
2117                 }
2118         }
2119
2120         /* Pipe is bound - set up auth_type and auth_level data. */
2121
2122         cli->auth.auth_type = auth_type;
2123         cli->auth.auth_level = auth_level;
2124
2125         prs_mem_free(&rbuf);
2126         return NT_STATUS_OK;
2127 }
2128
2129 unsigned int rpccli_set_timeout(struct rpc_pipe_client *cli,
2130                                 unsigned int timeout)
2131 {
2132         return cli_set_timeout(cli->cli, timeout);
2133 }
2134
2135 bool rpccli_is_pipe_idx(struct rpc_pipe_client *cli, int pipe_idx)
2136 {
2137         return (cli->abstract_syntax == pipe_names[pipe_idx].abstr_syntax);
2138 }
2139
2140 /****************************************************************************
2141  Open a named pipe over SMB to a remote server.
2142  *
2143  * CAVEAT CALLER OF THIS FUNCTION:
2144  *    The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2145  *    so be sure that this function is called AFTER any structure (vs pointer)
2146  *    assignment of the cli.  In particular, libsmbclient does structure
2147  *    assignments of cli, which invalidates the data in the returned
2148  *    rpc_pipe_client if this function is called before the structure assignment
2149  *    of cli.
2150  * 
2151  ****************************************************************************/
2152
2153 static struct rpc_pipe_client *cli_rpc_pipe_open(struct cli_state *cli, int pipe_idx, NTSTATUS *perr)
2154 {
2155         struct rpc_pipe_client *result;
2156         int fnum;
2157
2158         *perr = NT_STATUS_NO_MEMORY;
2159
2160         /* sanity check to protect against crashes */
2161
2162         if ( !cli ) {
2163                 *perr = NT_STATUS_INVALID_HANDLE;
2164                 return NULL;
2165         }
2166
2167         /* The pipe name index must fall within our array */
2168         SMB_ASSERT((pipe_idx >= 0) && (pipe_idx < PI_MAX_PIPES));
2169
2170         result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
2171         if (result == NULL) {
2172                 *perr = NT_STATUS_NO_MEMORY;
2173                 return NULL;
2174         }
2175
2176         result->pipe_name = cli_get_pipe_name(pipe_idx);
2177
2178         result->cli = cli;
2179         result->abstract_syntax = pipe_names[pipe_idx].abstr_syntax;
2180         result->transfer_syntax = pipe_names[pipe_idx].trans_syntax;
2181         result->auth.auth_type = PIPE_AUTH_TYPE_NONE;
2182         result->auth.auth_level = PIPE_AUTH_LEVEL_NONE;
2183
2184         result->domain = talloc_strdup(result, cli->domain);
2185         result->user_name = talloc_strdup(result, cli->user_name);
2186         result->desthost = talloc_strdup(result, cli->desthost);
2187         result->srv_name_slash = talloc_asprintf_strupper_m(
2188                 result, "\\\\%s", result->desthost);
2189
2190         if ((result->domain == NULL)
2191             || (result->user_name == NULL)
2192             || (result->desthost == NULL)
2193             || (result->srv_name_slash == NULL)) {
2194                 *perr = NT_STATUS_NO_MEMORY;
2195                 TALLOC_FREE(result);
2196                 return NULL;
2197         }
2198
2199         if (pipe_idx == PI_NETLOGON) {
2200                 /* Set up a netlogon credential chain for a netlogon pipe. */
2201                 result->dc = TALLOC_ZERO_P(result, struct dcinfo);
2202                 if (result->dc == NULL) {
2203                         *perr = NT_STATUS_NO_MEMORY;
2204                         TALLOC_FREE(result);
2205                         return NULL;
2206                 }
2207         }
2208
2209         fnum = cli_nt_create(cli, result->pipe_name, DESIRED_ACCESS_PIPE);
2210         if (fnum == -1) {
2211                 DEBUG(1,("cli_rpc_pipe_open: cli_nt_create failed on pipe %s "
2212                          "to machine %s.  Error was %s\n",
2213                          result->pipe_name, cli->desthost,
2214                          cli_errstr(cli)));
2215                 *perr = cli_get_nt_error(cli);
2216                 talloc_destroy(result);
2217                 return NULL;
2218         }
2219
2220         result->fnum = fnum;
2221
2222         DLIST_ADD(cli->pipe_list, result);
2223         *perr = NT_STATUS_OK;
2224
2225         return result;
2226 }
2227
2228 /****************************************************************************
2229  Open a named pipe to an SMB server and bind anonymously.
2230  ****************************************************************************/
2231
2232 struct rpc_pipe_client *cli_rpc_pipe_open_noauth(struct cli_state *cli, int pipe_idx, NTSTATUS *perr)
2233 {
2234         struct rpc_pipe_client *result;
2235
2236         result = cli_rpc_pipe_open(cli, pipe_idx, perr);
2237         if (result == NULL) {
2238                 return NULL;
2239         }
2240
2241         *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_NONE, PIPE_AUTH_LEVEL_NONE);
2242         if (!NT_STATUS_IS_OK(*perr)) {
2243                 int lvl = 0;
2244                 if (rpccli_is_pipe_idx(result, PI_DSSETUP)) {
2245                         /* non AD domains just don't have this pipe, avoid
2246                          * level 0 statement in that case - gd */
2247                         lvl = 3;
2248                 }
2249                 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe %s failed with error %s\n",
2250                         cli_get_pipe_name(pipe_idx), nt_errstr(*perr) ));
2251                 cli_rpc_pipe_close(result);
2252                 return NULL;
2253         }
2254
2255         DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine %s and bound anonymously.\n",
2256                         result->pipe_name, cli->desthost ));
2257
2258         return result;
2259 }
2260
2261 /****************************************************************************
2262  Free function for NTLMSSP auth.
2263  ****************************************************************************/
2264
2265 static void cli_ntlmssp_auth_free(struct cli_pipe_auth_data *auth)
2266 {
2267         if (auth->a_u.ntlmssp_state) {
2268                 ntlmssp_end(&auth->a_u.ntlmssp_state);
2269                 auth->a_u.ntlmssp_state = NULL;
2270         }
2271 }
2272
2273 /****************************************************************************
2274  Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
2275  ****************************************************************************/
2276
2277 static struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
2278                                                 int pipe_idx,
2279                                                 enum pipe_auth_type auth_type,
2280                                                 enum pipe_auth_level auth_level,
2281                                                 const char *domain,
2282                                                 const char *username,
2283                                                 const char *password,
2284                                                 NTSTATUS *perr)
2285 {
2286         struct rpc_pipe_client *result;
2287         NTLMSSP_STATE *ntlmssp_state = NULL;
2288
2289         result = cli_rpc_pipe_open(cli, pipe_idx, perr);
2290         if (result == NULL) {
2291                 return NULL;
2292         }
2293         
2294         result->auth.cli_auth_data_free_func = cli_ntlmssp_auth_free;
2295
2296         TALLOC_FREE(result->domain);
2297         TALLOC_FREE(result->user_name);
2298
2299         result->domain = talloc_strdup(result, domain);
2300         result->user_name = talloc_strdup(result, username);
2301
2302         if ((result->domain == NULL) || (result->user_name == NULL)) {
2303                 *perr = NT_STATUS_NO_MEMORY;
2304                 goto err;
2305         }
2306
2307         pwd_set_cleartext(&result->pwd, password);
2308
2309         *perr = ntlmssp_client_start(&ntlmssp_state);
2310         if (!NT_STATUS_IS_OK(*perr)) {
2311                 goto err;
2312         }
2313
2314         result->auth.a_u.ntlmssp_state = ntlmssp_state;
2315
2316         *perr = ntlmssp_set_username(ntlmssp_state, username);
2317         if (!NT_STATUS_IS_OK(*perr)) {
2318                 goto err;
2319         }
2320
2321         *perr = ntlmssp_set_domain(ntlmssp_state, domain);
2322         if (!NT_STATUS_IS_OK(*perr)) {
2323                 goto err;
2324         }
2325
2326         if (cli->pwd.null_pwd) {
2327                 *perr = ntlmssp_set_password(ntlmssp_state, NULL);
2328                 if (!NT_STATUS_IS_OK(*perr)) {
2329                         goto err;
2330                 }
2331         } else {
2332                 *perr = ntlmssp_set_password(ntlmssp_state, password);
2333                 if (!NT_STATUS_IS_OK(*perr)) {
2334                         goto err;
2335                 }
2336         }
2337
2338         /* Turn off sign+seal to allow selected auth level to turn it back on. */
2339         ntlmssp_state->neg_flags &= ~(NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL);
2340
2341         if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
2342                 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
2343         } else if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
2344                 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
2345         }
2346         
2347         *perr = rpc_pipe_bind(result, auth_type, auth_level);
2348         if (!NT_STATUS_IS_OK(*perr)) {
2349                 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
2350                         nt_errstr(*perr) ));
2351                 goto err;
2352         }
2353
2354         DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
2355                 "machine %s and bound NTLMSSP as user %s\\%s.\n",
2356                 result->pipe_name, cli->desthost,
2357                 domain, username ));
2358
2359         return result;
2360
2361   err:
2362
2363         cli_rpc_pipe_close(result);
2364         return NULL;
2365 }
2366
2367 /****************************************************************************
2368  External interface.
2369  Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
2370  ****************************************************************************/
2371
2372 struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
2373                                                 int pipe_idx,
2374                                                 enum pipe_auth_level auth_level,
2375                                                 const char *domain,
2376                                                 const char *username,
2377                                                 const char *password,
2378                                                 NTSTATUS *perr)
2379 {
2380         return cli_rpc_pipe_open_ntlmssp_internal(cli,
2381                                                 pipe_idx,
2382                                                 PIPE_AUTH_TYPE_NTLMSSP,
2383                                                 auth_level,
2384                                                 domain,
2385                                                 username,
2386                                                 password,
2387                                                 perr);
2388 }
2389
2390 /****************************************************************************
2391  External interface.
2392  Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
2393  ****************************************************************************/
2394
2395 struct rpc_pipe_client *cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
2396                                                 int pipe_idx,
2397                                                 enum pipe_auth_level auth_level,
2398                                                 const char *domain,
2399                                                 const char *username,
2400                                                 const char *password,
2401                                                 NTSTATUS *perr)
2402 {
2403         return cli_rpc_pipe_open_ntlmssp_internal(cli,
2404                                                 pipe_idx,
2405                                                 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
2406                                                 auth_level,
2407                                                 domain,
2408                                                 username,
2409                                                 password,
2410                                                 perr);
2411 }
2412
2413 /****************************************************************************
2414   Get a the schannel session key out of an already opened netlogon pipe.
2415  ****************************************************************************/
2416 static bool get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
2417                                             struct cli_state *cli,
2418                                             const char *domain,
2419                                             uint32 *pneg_flags,
2420                                             NTSTATUS *perr)
2421 {
2422         uint32 sec_chan_type = 0;
2423         unsigned char machine_pwd[16];
2424         const char *machine_account;
2425
2426         /* Get the machine account credentials from secrets.tdb. */
2427         if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
2428                                &sec_chan_type))
2429         {
2430                 DEBUG(0, ("get_schannel_session_key: could not fetch "
2431                         "trust account password for domain '%s'\n",
2432                         domain));
2433                 *perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2434                 return false;
2435         }
2436
2437         *perr = rpccli_netlogon_setup_creds(netlogon_pipe,
2438                                         cli->desthost, /* server name */
2439                                         domain,        /* domain */
2440                                         global_myname(), /* client name */
2441                                         machine_account, /* machine account name */
2442                                         machine_pwd,
2443                                         sec_chan_type,
2444                                         pneg_flags);
2445
2446         if (!NT_STATUS_IS_OK(*perr)) {
2447                 DEBUG(3,("get_schannel_session_key_common: rpccli_netlogon_setup_creds "
2448                         "failed with result %s to server %s, domain %s, machine account %s.\n",
2449                         nt_errstr(*perr), cli->desthost, domain, machine_account ));
2450                 return false;
2451         }
2452
2453         if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
2454                 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
2455                         cli->desthost));
2456                 *perr = NT_STATUS_INVALID_NETWORK_RESPONSE;
2457                 return false;
2458         }
2459
2460         return true;
2461 }
2462
2463 /****************************************************************************
2464  Open a netlogon pipe and get the schannel session key.
2465  Now exposed to external callers.
2466  ****************************************************************************/
2467
2468
2469 struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli,
2470                                                         const char *domain,
2471                                                         uint32 *pneg_flags,
2472                                                         NTSTATUS *perr)
2473 {
2474         struct rpc_pipe_client *netlogon_pipe = NULL;
2475
2476         netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, perr);
2477         if (!netlogon_pipe) {
2478                 return NULL;
2479         }
2480
2481         if (!get_schannel_session_key_common(netlogon_pipe, cli, domain,
2482                                              pneg_flags, perr))
2483         {
2484                 cli_rpc_pipe_close(netlogon_pipe);
2485                 return NULL;
2486         }
2487
2488         return netlogon_pipe;
2489 }
2490
2491 /****************************************************************************
2492  External interface.
2493  Open a named pipe to an SMB server and bind using schannel (bind type 68)
2494  using session_key. sign and seal.
2495  ****************************************************************************/
2496
2497 struct rpc_pipe_client *cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
2498                                         int pipe_idx,
2499                                         enum pipe_auth_level auth_level,
2500                                         const char *domain,
2501                                         const struct dcinfo *pdc,
2502                                         NTSTATUS *perr)
2503 {
2504         struct rpc_pipe_client *result;
2505
2506         result = cli_rpc_pipe_open(cli, pipe_idx, perr);
2507         if (result == NULL) {
2508                 return NULL;
2509         }
2510
2511         result->auth.a_u.schannel_auth = TALLOC_ZERO_P(
2512                 result, struct schannel_auth_struct);
2513         if (!result->auth.a_u.schannel_auth) {
2514                 cli_rpc_pipe_close(result);
2515                 *perr = NT_STATUS_NO_MEMORY;
2516                 return NULL;
2517         }
2518
2519         TALLOC_FREE(result->domain);
2520         result->domain = talloc_strdup(result, domain);
2521         if (result->domain == NULL) {
2522                 cli_rpc_pipe_close(result);
2523                 *perr = NT_STATUS_NO_MEMORY;
2524                 return NULL;
2525         }
2526
2527         memcpy(result->auth.a_u.schannel_auth->sess_key, pdc->sess_key, 16);
2528
2529         *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_SCHANNEL, auth_level);
2530         if (!NT_STATUS_IS_OK(*perr)) {
2531                 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: cli_rpc_pipe_bind failed with error %s\n",
2532                         nt_errstr(*perr) ));
2533                 cli_rpc_pipe_close(result);
2534                 return NULL;
2535         }
2536
2537         /* The credentials on a new netlogon pipe are the ones we are passed in - copy them over. */
2538         if (result->dc) {
2539                 *result->dc = *pdc;
2540         }
2541
2542         DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
2543                 "for domain %s "
2544                 "and bound using schannel.\n",
2545                 result->pipe_name, cli->desthost, domain ));
2546
2547         return result;
2548 }
2549
2550 /****************************************************************************
2551  Open a named pipe to an SMB server and bind using schannel (bind type 68).
2552  Fetch the session key ourselves using a temporary netlogon pipe. This
2553  version uses an ntlmssp auth bound netlogon pipe to get the key.
2554  ****************************************************************************/
2555
2556 static struct rpc_pipe_client *get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
2557                                                         const char *domain,
2558                                                         const char *username,
2559                                                         const char *password,
2560                                                         uint32 *pneg_flags,
2561                                                         NTSTATUS *perr)
2562 {
2563         struct rpc_pipe_client *netlogon_pipe = NULL;
2564
2565         netlogon_pipe = cli_rpc_pipe_open_spnego_ntlmssp(cli, PI_NETLOGON, PIPE_AUTH_LEVEL_PRIVACY, domain, username, password, perr);
2566         if (!netlogon_pipe) {
2567                 return NULL;
2568         }
2569
2570         if (!get_schannel_session_key_common(netlogon_pipe, cli, domain,
2571                                              pneg_flags, perr))
2572         {
2573                 cli_rpc_pipe_close(netlogon_pipe);
2574                 return NULL;
2575         }
2576
2577         return netlogon_pipe;
2578 }
2579
2580 /****************************************************************************
2581  Open a named pipe to an SMB server and bind using schannel (bind type 68).
2582  Fetch the session key ourselves using a temporary netlogon pipe. This version
2583  uses an ntlmssp bind to get the session key.
2584  ****************************************************************************/
2585
2586 struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
2587                                                 int pipe_idx,
2588                                                 enum pipe_auth_level auth_level,
2589                                                 const char *domain,
2590                                                 const char *username,
2591                                                 const char *password,
2592                                                 NTSTATUS *perr)
2593 {
2594         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2595         struct rpc_pipe_client *netlogon_pipe = NULL;
2596         struct rpc_pipe_client *result = NULL;
2597
2598         netlogon_pipe = get_schannel_session_key_auth_ntlmssp(cli, domain, username,
2599                                                         password, &neg_flags, perr);
2600         if (!netlogon_pipe) {
2601                 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
2602                         "key from server %s for domain %s.\n",
2603                         cli->desthost, domain ));
2604                 return NULL;
2605         }
2606
2607         result = cli_rpc_pipe_open_schannel_with_key(cli, pipe_idx,
2608                                 auth_level,
2609                                 domain, netlogon_pipe->dc, perr);
2610
2611         /* Now we've bound using the session key we can close the netlog pipe. */
2612         cli_rpc_pipe_close(netlogon_pipe);
2613
2614         return result;
2615 }
2616
2617 /****************************************************************************
2618  Open a named pipe to an SMB server and bind using schannel (bind type 68).
2619  Fetch the session key ourselves using a temporary netlogon pipe.
2620  ****************************************************************************/
2621
2622 struct rpc_pipe_client *cli_rpc_pipe_open_schannel(struct cli_state *cli,
2623                                                 int pipe_idx,
2624                                                 enum pipe_auth_level auth_level,
2625                                                 const char *domain,
2626                                                 NTSTATUS *perr)
2627 {
2628         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
2629         struct rpc_pipe_client *netlogon_pipe = NULL;
2630         struct rpc_pipe_client *result = NULL;
2631
2632         netlogon_pipe = get_schannel_session_key(cli, domain, &neg_flags, perr);
2633         if (!netlogon_pipe) {
2634                 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
2635                         "key from server %s for domain %s.\n",
2636                         cli->desthost, domain ));
2637                 return NULL;
2638         }
2639
2640         result = cli_rpc_pipe_open_schannel_with_key(cli, pipe_idx,
2641                                 auth_level,
2642                                 domain, netlogon_pipe->dc, perr);
2643
2644         /* Now we've bound using the session key we can close the netlog pipe. */
2645         cli_rpc_pipe_close(netlogon_pipe);
2646
2647         return result;
2648 }
2649
2650 #ifdef HAVE_KRB5
2651
2652 /****************************************************************************
2653  Free function for the kerberos spcific data.
2654  ****************************************************************************/
2655
2656 static void kerberos_auth_struct_free(struct cli_pipe_auth_data *a)
2657 {
2658         data_blob_free(&a->a_u.kerberos_auth->session_key);
2659 }
2660
2661 #endif
2662
2663 /****************************************************************************
2664  Open a named pipe to an SMB server and bind using krb5 (bind type 16).
2665  The idea is this can be called with service_princ, username and password all
2666  NULL so long as the caller has a TGT.
2667  ****************************************************************************/
2668
2669 struct rpc_pipe_client *cli_rpc_pipe_open_krb5(struct cli_state *cli,
2670                                                 int pipe_idx,
2671                                                 enum pipe_auth_level auth_level,
2672                                                 const char *service_princ,
2673                                                 const char *username,
2674                                                 const char *password,
2675                                                 NTSTATUS *perr)
2676 {
2677 #ifdef HAVE_KRB5
2678         struct rpc_pipe_client *result;
2679
2680         result = cli_rpc_pipe_open(cli, pipe_idx, perr);
2681         if (result == NULL) {
2682                 return NULL;
2683         }
2684
2685         /* Default service principal is "desthost$@realm" */
2686         if (!service_princ) {
2687                 service_princ = talloc_asprintf(result, "%s$@%s",
2688                                                 cli->desthost, lp_realm() );
2689                 if (!service_princ) {
2690                         cli_rpc_pipe_close(result);
2691                         return NULL;
2692                 }
2693         }
2694
2695         /* Only get a new TGT if username/password are given. */
2696         if (username && password) {
2697                 int ret = kerberos_kinit_password(username, password, 0, NULL);
2698                 if (ret) {
2699                         cli_rpc_pipe_close(result);
2700                         return NULL;
2701                 }
2702         }
2703
2704         result->auth.a_u.kerberos_auth = TALLOC_ZERO_P(
2705                 result, struct kerberos_auth_struct);
2706         if (!result->auth.a_u.kerberos_auth) {
2707                 cli_rpc_pipe_close(result);
2708                 *perr = NT_STATUS_NO_MEMORY;
2709                 return NULL;
2710         }
2711
2712         result->auth.a_u.kerberos_auth->service_principal = service_princ;
2713         result->auth.cli_auth_data_free_func = kerberos_auth_struct_free;
2714
2715         *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_KRB5, auth_level);
2716         if (!NT_STATUS_IS_OK(*perr)) {
2717                 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed with error %s\n",
2718                         nt_errstr(*perr) ));
2719                 cli_rpc_pipe_close(result);
2720                 return NULL;
2721         }
2722
2723         return result;
2724 #else
2725         DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
2726         return NULL;
2727 #endif
2728 }