Convert the prs_XXX struct and functions to use talloc instead of malloc. Passes...
[mat/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 #include "librpc/gen_ndr/cli_epmapper.h"
22 #include "../librpc/gen_ndr/ndr_schannel.h"
23 #include "../librpc/gen_ndr/ndr_lsa.h"
24 #include "../librpc/gen_ndr/ndr_dssetup.h"
25 #include "../librpc/gen_ndr/ndr_samr.h"
26 #include "../librpc/gen_ndr/ndr_netlogon.h"
27 #include "../librpc/gen_ndr/ndr_srvsvc.h"
28 #include "../librpc/gen_ndr/ndr_wkssvc.h"
29 #include "../librpc/gen_ndr/ndr_winreg.h"
30 #include "../librpc/gen_ndr/ndr_spoolss.h"
31 #include "../librpc/gen_ndr/ndr_dfs.h"
32 #include "../librpc/gen_ndr/ndr_echo.h"
33 #include "../librpc/gen_ndr/ndr_initshutdown.h"
34 #include "../librpc/gen_ndr/ndr_svcctl.h"
35 #include "../librpc/gen_ndr/ndr_eventlog.h"
36 #include "../librpc/gen_ndr/ndr_ntsvcs.h"
37 #include "../librpc/gen_ndr/ndr_epmapper.h"
38 #include "../librpc/gen_ndr/ndr_drsuapi.h"
39 #include "../libcli/auth/schannel.h"
40 #include "../libcli/auth/spnego.h"
41 #include "smb_krb5.h"
42 #include "../libcli/auth/ntlmssp.h"
43 #include "rpc_client/cli_netlogon.h"
44
45 #undef DBGC_CLASS
46 #define DBGC_CLASS DBGC_RPC_CLI
47
48 static const char *get_pipe_name_from_iface(
49         TALLOC_CTX *mem_ctx, const struct ndr_interface_table *interface)
50 {
51         int i;
52         const struct ndr_interface_string_array *ep = interface->endpoints;
53         char *p;
54
55         for (i=0; i<ep->count; i++) {
56                 if (strncmp(ep->names[i], "ncacn_np:[\\pipe\\", 16) == 0) {
57                         break;
58                 }
59         }
60         if (i == ep->count) {
61                 return NULL;
62         }
63
64         /*
65          * extract the pipe name without \\pipe from for example
66          * ncacn_np:[\\pipe\\epmapper]
67          */
68         p = strchr(ep->names[i]+15, ']');
69         if (p == NULL) {
70                 return "PIPE";
71         }
72         return talloc_strndup(mem_ctx, ep->names[i]+15, p - ep->names[i] - 15);
73 }
74
75 static const struct ndr_interface_table **interfaces;
76
77 bool smb_register_ndr_interface(const struct ndr_interface_table *interface)
78 {
79         int num_interfaces = talloc_array_length(interfaces);
80         const struct ndr_interface_table **tmp;
81         int i;
82
83         for (i=0; i<num_interfaces; i++) {
84                 if (ndr_syntax_id_equal(&interfaces[i]->syntax_id,
85                                         &interface->syntax_id)) {
86                         return true;
87                 }
88         }
89
90         tmp = talloc_realloc(NULL, interfaces,
91                              const struct ndr_interface_table *,
92                              num_interfaces + 1);
93         if (tmp == NULL) {
94                 DEBUG(1, ("smb_register_ndr_interface: talloc failed\n"));
95                 return false;
96         }
97         interfaces = tmp;
98         interfaces[num_interfaces] = interface;
99         return true;
100 }
101
102 static bool initialize_interfaces(void)
103 {
104         if (!smb_register_ndr_interface(&ndr_table_lsarpc)) {
105                 return false;
106         }
107         if (!smb_register_ndr_interface(&ndr_table_dssetup)) {
108                 return false;
109         }
110         if (!smb_register_ndr_interface(&ndr_table_samr)) {
111                 return false;
112         }
113         if (!smb_register_ndr_interface(&ndr_table_netlogon)) {
114                 return false;
115         }
116         if (!smb_register_ndr_interface(&ndr_table_srvsvc)) {
117                 return false;
118         }
119         if (!smb_register_ndr_interface(&ndr_table_wkssvc)) {
120                 return false;
121         }
122         if (!smb_register_ndr_interface(&ndr_table_winreg)) {
123                 return false;
124         }
125         if (!smb_register_ndr_interface(&ndr_table_spoolss)) {
126                 return false;
127         }
128         if (!smb_register_ndr_interface(&ndr_table_netdfs)) {
129                 return false;
130         }
131         if (!smb_register_ndr_interface(&ndr_table_rpcecho)) {
132                 return false;
133         }
134         if (!smb_register_ndr_interface(&ndr_table_initshutdown)) {
135                 return false;
136         }
137         if (!smb_register_ndr_interface(&ndr_table_svcctl)) {
138                 return false;
139         }
140         if (!smb_register_ndr_interface(&ndr_table_eventlog)) {
141                 return false;
142         }
143         if (!smb_register_ndr_interface(&ndr_table_ntsvcs)) {
144                 return false;
145         }
146         if (!smb_register_ndr_interface(&ndr_table_epmapper)) {
147                 return false;
148         }
149         if (!smb_register_ndr_interface(&ndr_table_drsuapi)) {
150                 return false;
151         }
152         return true;
153 }
154
155 const struct ndr_interface_table *get_iface_from_syntax(
156         const struct ndr_syntax_id *syntax)
157 {
158         int num_interfaces;
159         int i;
160
161         if (interfaces == NULL) {
162                 if (!initialize_interfaces()) {
163                         return NULL;
164                 }
165         }
166         num_interfaces = talloc_array_length(interfaces);
167
168         for (i=0; i<num_interfaces; i++) {
169                 if (ndr_syntax_id_equal(&interfaces[i]->syntax_id, syntax)) {
170                         return interfaces[i];
171                 }
172         }
173
174         return NULL;
175 }
176
177 /****************************************************************************
178  Return the pipe name from the interface.
179  ****************************************************************************/
180
181 const char *get_pipe_name_from_syntax(TALLOC_CTX *mem_ctx,
182                                       const struct ndr_syntax_id *syntax)
183 {
184         const struct ndr_interface_table *interface;
185         char *guid_str;
186         const char *result;
187
188         interface = get_iface_from_syntax(syntax);
189         if (interface != NULL) {
190                 result = get_pipe_name_from_iface(mem_ctx, interface);
191                 if (result != NULL) {
192                         return result;
193                 }
194         }
195
196         /*
197          * Here we should ask \\epmapper, but for now our code is only
198          * interested in the known pipes mentioned in pipe_names[]
199          */
200
201         guid_str = GUID_string(talloc_tos(), &syntax->uuid);
202         if (guid_str == NULL) {
203                 return NULL;
204         }
205         result = talloc_asprintf(mem_ctx, "Interface %s.%d", guid_str,
206                                  (int)syntax->if_version);
207         TALLOC_FREE(guid_str);
208
209         if (result == NULL) {
210                 return "PIPE";
211         }
212         return result;
213 }
214
215 /********************************************************************
216  Map internal value to wire value.
217  ********************************************************************/
218
219 static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type)
220 {
221         switch (auth_type) {
222
223         case PIPE_AUTH_TYPE_NONE:
224                 return DCERPC_AUTH_TYPE_NONE;
225
226         case PIPE_AUTH_TYPE_NTLMSSP:
227                 return DCERPC_AUTH_TYPE_NTLMSSP;
228
229         case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
230         case PIPE_AUTH_TYPE_SPNEGO_KRB5:
231                 return DCERPC_AUTH_TYPE_SPNEGO;
232
233         case PIPE_AUTH_TYPE_SCHANNEL:
234                 return DCERPC_AUTH_TYPE_SCHANNEL;
235
236         case PIPE_AUTH_TYPE_KRB5:
237                 return DCERPC_AUTH_TYPE_KRB5;
238
239         default:
240                 DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe "
241                         "auth type %u\n",
242                         (unsigned int)auth_type ));
243                 break;
244         }
245         return -1;
246 }
247
248 /********************************************************************
249  Pipe description for a DEBUG
250  ********************************************************************/
251 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
252                                    struct rpc_pipe_client *cli)
253 {
254         char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
255         if (result == NULL) {
256                 return "pipe";
257         }
258         return result;
259 }
260
261 /********************************************************************
262  Rpc pipe call id.
263  ********************************************************************/
264
265 static uint32 get_rpc_call_id(void)
266 {
267         static uint32 call_id = 0;
268         return ++call_id;
269 }
270
271 /*
272  * Realloc pdu to have a least "size" bytes
273  */
274
275 static bool rpc_grow_buffer(prs_struct *pdu, size_t size)
276 {
277         size_t extra_size;
278
279         if (prs_data_size(pdu) >= size) {
280                 return true;
281         }
282
283         extra_size = size - prs_data_size(pdu);
284
285         if (!prs_force_grow(pdu, extra_size)) {
286                 DEBUG(0, ("rpc_grow_buffer: Failed to grow parse struct by "
287                           "%d bytes.\n", (int)extra_size));
288                 return false;
289         }
290
291         DEBUG(5, ("rpc_grow_buffer: grew buffer by %d bytes to %u\n",
292                   (int)extra_size, prs_data_size(pdu)));
293         return true;
294 }
295
296
297 /*******************************************************************
298  Use SMBreadX to get rest of one fragment's worth of rpc data.
299  Reads the whole size or give an error message
300  ********************************************************************/
301
302 struct rpc_read_state {
303         struct event_context *ev;
304         struct rpc_cli_transport *transport;
305         uint8_t *data;
306         size_t size;
307         size_t num_read;
308 };
309
310 static void rpc_read_done(struct tevent_req *subreq);
311
312 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
313                                         struct event_context *ev,
314                                         struct rpc_cli_transport *transport,
315                                         uint8_t *data, size_t size)
316 {
317         struct tevent_req *req, *subreq;
318         struct rpc_read_state *state;
319
320         req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
321         if (req == NULL) {
322                 return NULL;
323         }
324         state->ev = ev;
325         state->transport = transport;
326         state->data = data;
327         state->size = size;
328         state->num_read = 0;
329
330         DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
331
332         subreq = transport->read_send(state, ev, (uint8_t *)data, size,
333                                       transport->priv);
334         if (subreq == NULL) {
335                 goto fail;
336         }
337         tevent_req_set_callback(subreq, rpc_read_done, req);
338         return req;
339
340  fail:
341         TALLOC_FREE(req);
342         return NULL;
343 }
344
345 static void rpc_read_done(struct tevent_req *subreq)
346 {
347         struct tevent_req *req = tevent_req_callback_data(
348                 subreq, struct tevent_req);
349         struct rpc_read_state *state = tevent_req_data(
350                 req, struct rpc_read_state);
351         NTSTATUS status;
352         ssize_t received;
353
354         status = state->transport->read_recv(subreq, &received);
355         TALLOC_FREE(subreq);
356         if (!NT_STATUS_IS_OK(status)) {
357                 tevent_req_nterror(req, status);
358                 return;
359         }
360
361         state->num_read += received;
362         if (state->num_read == state->size) {
363                 tevent_req_done(req);
364                 return;
365         }
366
367         subreq = state->transport->read_send(state, state->ev,
368                                              state->data + state->num_read,
369                                              state->size - state->num_read,
370                                              state->transport->priv);
371         if (tevent_req_nomem(subreq, req)) {
372                 return;
373         }
374         tevent_req_set_callback(subreq, rpc_read_done, req);
375 }
376
377 static NTSTATUS rpc_read_recv(struct tevent_req *req)
378 {
379         return tevent_req_simple_recv_ntstatus(req);
380 }
381
382 struct rpc_write_state {
383         struct event_context *ev;
384         struct rpc_cli_transport *transport;
385         const uint8_t *data;
386         size_t size;
387         size_t num_written;
388 };
389
390 static void rpc_write_done(struct tevent_req *subreq);
391
392 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
393                                          struct event_context *ev,
394                                          struct rpc_cli_transport *transport,
395                                          const uint8_t *data, size_t size)
396 {
397         struct tevent_req *req, *subreq;
398         struct rpc_write_state *state;
399
400         req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
401         if (req == NULL) {
402                 return NULL;
403         }
404         state->ev = ev;
405         state->transport = transport;
406         state->data = data;
407         state->size = size;
408         state->num_written = 0;
409
410         DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
411
412         subreq = transport->write_send(state, ev, data, size, transport->priv);
413         if (subreq == NULL) {
414                 goto fail;
415         }
416         tevent_req_set_callback(subreq, rpc_write_done, req);
417         return req;
418  fail:
419         TALLOC_FREE(req);
420         return NULL;
421 }
422
423 static void rpc_write_done(struct tevent_req *subreq)
424 {
425         struct tevent_req *req = tevent_req_callback_data(
426                 subreq, struct tevent_req);
427         struct rpc_write_state *state = tevent_req_data(
428                 req, struct rpc_write_state);
429         NTSTATUS status;
430         ssize_t written;
431
432         status = state->transport->write_recv(subreq, &written);
433         TALLOC_FREE(subreq);
434         if (!NT_STATUS_IS_OK(status)) {
435                 tevent_req_nterror(req, status);
436                 return;
437         }
438
439         state->num_written += written;
440
441         if (state->num_written == state->size) {
442                 tevent_req_done(req);
443                 return;
444         }
445
446         subreq = state->transport->write_send(state, state->ev,
447                                               state->data + state->num_written,
448                                               state->size - state->num_written,
449                                               state->transport->priv);
450         if (tevent_req_nomem(subreq, req)) {
451                 return;
452         }
453         tevent_req_set_callback(subreq, rpc_write_done, req);
454 }
455
456 static NTSTATUS rpc_write_recv(struct tevent_req *req)
457 {
458         return tevent_req_simple_recv_ntstatus(req);
459 }
460
461
462 static NTSTATUS parse_rpc_header(struct rpc_pipe_client *cli,
463                                  struct rpc_hdr_info *prhdr,
464                                  prs_struct *pdu)
465 {
466         /*
467          * This next call sets the endian bit correctly in current_pdu. We
468          * will propagate this to rbuf later.
469          */
470
471         if(!smb_io_rpc_hdr("rpc_hdr   ", prhdr, pdu, 0)) {
472                 DEBUG(0, ("get_current_pdu: Failed to unmarshall RPC_HDR.\n"));
473                 return NT_STATUS_BUFFER_TOO_SMALL;
474         }
475
476         if (prhdr->frag_len > cli->max_recv_frag) {
477                 DEBUG(0, ("cli_pipe_get_current_pdu: Server sent fraglen %d,"
478                           " we only allow %d\n", (int)prhdr->frag_len,
479                           (int)cli->max_recv_frag));
480                 return NT_STATUS_BUFFER_TOO_SMALL;
481         }
482
483         return NT_STATUS_OK;
484 }
485
486 /****************************************************************************
487  Try and get a PDU's worth of data from current_pdu. If not, then read more
488  from the wire.
489  ****************************************************************************/
490
491 struct get_complete_frag_state {
492         struct event_context *ev;
493         struct rpc_pipe_client *cli;
494         struct rpc_hdr_info *prhdr;
495         prs_struct *pdu;
496 };
497
498 static void get_complete_frag_got_header(struct tevent_req *subreq);
499 static void get_complete_frag_got_rest(struct tevent_req *subreq);
500
501 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
502                                                  struct event_context *ev,
503                                                  struct rpc_pipe_client *cli,
504                                                  struct rpc_hdr_info *prhdr,
505                                                  prs_struct *pdu)
506 {
507         struct tevent_req *req, *subreq;
508         struct get_complete_frag_state *state;
509         uint32_t pdu_len;
510         NTSTATUS status;
511
512         req = tevent_req_create(mem_ctx, &state,
513                                 struct get_complete_frag_state);
514         if (req == NULL) {
515                 return NULL;
516         }
517         state->ev = ev;
518         state->cli = cli;
519         state->prhdr = prhdr;
520         state->pdu = pdu;
521
522         pdu_len = prs_data_size(pdu);
523         if (pdu_len < RPC_HEADER_LEN) {
524                 if (!rpc_grow_buffer(pdu, RPC_HEADER_LEN)) {
525                         status = NT_STATUS_NO_MEMORY;
526                         goto post_status;
527                 }
528                 subreq = rpc_read_send(
529                         state, state->ev,
530                         state->cli->transport,
531                         (uint8_t *)(prs_data_p(state->pdu) + pdu_len),
532                         RPC_HEADER_LEN - pdu_len);
533                 if (subreq == NULL) {
534                         status = NT_STATUS_NO_MEMORY;
535                         goto post_status;
536                 }
537                 tevent_req_set_callback(subreq, get_complete_frag_got_header,
538                                         req);
539                 return req;
540         }
541
542         status = parse_rpc_header(cli, prhdr, pdu);
543         if (!NT_STATUS_IS_OK(status)) {
544                 goto post_status;
545         }
546
547         /*
548          * Ensure we have frag_len bytes of data.
549          */
550         if (pdu_len < prhdr->frag_len) {
551                 if (!rpc_grow_buffer(pdu, prhdr->frag_len)) {
552                         status = NT_STATUS_NO_MEMORY;
553                         goto post_status;
554                 }
555                 subreq = rpc_read_send(state, state->ev,
556                                        state->cli->transport,
557                                        (uint8_t *)(prs_data_p(pdu) + pdu_len),
558                                        prhdr->frag_len - pdu_len);
559                 if (subreq == NULL) {
560                         status = NT_STATUS_NO_MEMORY;
561                         goto post_status;
562                 }
563                 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
564                                         req);
565                 return req;
566         }
567
568         status = NT_STATUS_OK;
569  post_status:
570         if (NT_STATUS_IS_OK(status)) {
571                 tevent_req_done(req);
572         } else {
573                 tevent_req_nterror(req, status);
574         }
575         return tevent_req_post(req, ev);
576 }
577
578 static void get_complete_frag_got_header(struct tevent_req *subreq)
579 {
580         struct tevent_req *req = tevent_req_callback_data(
581                 subreq, struct tevent_req);
582         struct get_complete_frag_state *state = tevent_req_data(
583                 req, struct get_complete_frag_state);
584         NTSTATUS status;
585
586         status = rpc_read_recv(subreq);
587         TALLOC_FREE(subreq);
588         if (!NT_STATUS_IS_OK(status)) {
589                 tevent_req_nterror(req, status);
590                 return;
591         }
592
593         status = parse_rpc_header(state->cli, state->prhdr, state->pdu);
594         if (!NT_STATUS_IS_OK(status)) {
595                 tevent_req_nterror(req, status);
596                 return;
597         }
598
599         if (!rpc_grow_buffer(state->pdu, state->prhdr->frag_len)) {
600                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
601                 return;
602         }
603
604         /*
605          * We're here in this piece of code because we've read exactly
606          * RPC_HEADER_LEN bytes into state->pdu.
607          */
608
609         subreq = rpc_read_send(
610                 state, state->ev, state->cli->transport,
611                 (uint8_t *)(prs_data_p(state->pdu) + RPC_HEADER_LEN),
612                 state->prhdr->frag_len - RPC_HEADER_LEN);
613         if (tevent_req_nomem(subreq, req)) {
614                 return;
615         }
616         tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
617 }
618
619 static void get_complete_frag_got_rest(struct tevent_req *subreq)
620 {
621         struct tevent_req *req = tevent_req_callback_data(
622                 subreq, struct tevent_req);
623         NTSTATUS status;
624
625         status = rpc_read_recv(subreq);
626         TALLOC_FREE(subreq);
627         if (!NT_STATUS_IS_OK(status)) {
628                 tevent_req_nterror(req, status);
629                 return;
630         }
631         tevent_req_done(req);
632 }
633
634 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
635 {
636         return tevent_req_simple_recv_ntstatus(req);
637 }
638
639 /****************************************************************************
640  NTLMSSP specific sign/seal.
641  Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
642  In fact I should probably abstract these into identical pieces of code... JRA.
643  ****************************************************************************/
644
645 static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
646                                 prs_struct *current_pdu,
647                                 uint8 *p_ss_padding_len)
648 {
649         RPC_HDR_AUTH auth_info;
650         uint32 save_offset = prs_offset(current_pdu);
651         uint32 auth_len = prhdr->auth_len;
652         struct ntlmssp_state *ntlmssp_state = cli->auth->a_u.ntlmssp_state;
653         unsigned char *data = NULL;
654         size_t data_len;
655         unsigned char *full_packet_data = NULL;
656         size_t full_packet_data_len;
657         DATA_BLOB auth_blob;
658         NTSTATUS status;
659
660         if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE
661             || cli->auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
662                 return NT_STATUS_OK;
663         }
664
665         if (!ntlmssp_state) {
666                 return NT_STATUS_INVALID_PARAMETER;
667         }
668
669         /* Ensure there's enough data for an authenticated response. */
670         if (auth_len > RPC_MAX_PDU_FRAG_LEN ||
671                         prhdr->frag_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN +
672                                         RPC_HDR_AUTH_LEN + auth_len) {
673                 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n",
674                         (unsigned int)auth_len ));
675                 return NT_STATUS_BUFFER_TOO_SMALL;
676         }
677
678         /*
679          * We need the full packet data + length (minus auth stuff) as well as the packet data + length
680          * after the RPC header.
681          * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
682          * functions as NTLMv2 checks the rpc headers also.
683          */
684
685         data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN);
686         data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len);
687
688         full_packet_data = (unsigned char *)prs_data_p(current_pdu);
689         full_packet_data_len = prhdr->frag_len - auth_len;
690
691         /* Pull the auth header and the following data into a blob. */
692         /* NB. The offset of the auth_header is relative to the *end*
693          * of the packet, not the start. */
694         if(!prs_set_offset(current_pdu, prhdr->frag_len - RPC_HDR_AUTH_LEN - auth_len)) {
695                 DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n",
696                         (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len ));
697                 return NT_STATUS_BUFFER_TOO_SMALL;
698         }
699
700         if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
701                 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n"));
702                 return NT_STATUS_BUFFER_TOO_SMALL;
703         }
704
705         /* Ensure auth_pad_len fits into the packet. */
706         if (RPC_HEADER_LEN + RPC_HDR_REQ_LEN + auth_info.auth_pad_len +
707                         RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len) {
708                 DEBUG(0,("cli_pipe_verify_ntlmssp: auth_info.auth_pad_len "
709                         "too large (%u), auth_len (%u), frag_len = (%u).\n",
710                         (unsigned int)auth_info.auth_pad_len,
711                         (unsigned int)auth_len,
712                         (unsigned int)prhdr->frag_len ));
713                 return NT_STATUS_BUFFER_TOO_SMALL;
714         }
715
716
717         auth_blob.data = (unsigned char *)prs_data_p(current_pdu) + prs_offset(current_pdu);
718         auth_blob.length = auth_len;
719
720         switch (cli->auth->auth_level) {
721                 case DCERPC_AUTH_LEVEL_PRIVACY:
722                         /* Data is encrypted. */
723                         status = ntlmssp_unseal_packet(ntlmssp_state,
724                                                         data, data_len,
725                                                         full_packet_data,
726                                                         full_packet_data_len,
727                                                         &auth_blob);
728                         if (!NT_STATUS_IS_OK(status)) {
729                                 DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
730                                         "packet from %s. Error was %s.\n",
731                                         rpccli_pipe_txt(talloc_tos(), cli),
732                                         nt_errstr(status) ));
733                                 return status;
734                         }
735                         break;
736                 case DCERPC_AUTH_LEVEL_INTEGRITY:
737                         /* Data is signed. */
738                         status = ntlmssp_check_packet(ntlmssp_state,
739                                                         data, data_len,
740                                                         full_packet_data,
741                                                         full_packet_data_len,
742                                                         &auth_blob);
743                         if (!NT_STATUS_IS_OK(status)) {
744                                 DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
745                                         "packet from %s. Error was %s.\n",
746                                         rpccli_pipe_txt(talloc_tos(), cli),
747                                         nt_errstr(status) ));
748                                 return status;
749                         }
750                         break;
751                 default:
752                         DEBUG(0, ("cli_pipe_verify_ntlmssp: unknown internal "
753                                   "auth level %d\n", cli->auth->auth_level));
754                         return NT_STATUS_INVALID_INFO_CLASS;
755         }
756
757         /*
758          * Return the current pointer to the data offset.
759          */
760
761         if(!prs_set_offset(current_pdu, save_offset)) {
762                 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
763                         (unsigned int)save_offset ));
764                 return NT_STATUS_BUFFER_TOO_SMALL;
765         }
766
767         /*
768          * Remember the padding length. We must remove it from the real data
769          * stream once the sign/seal is done.
770          */
771
772         *p_ss_padding_len = auth_info.auth_pad_len;
773
774         return NT_STATUS_OK;
775 }
776
777 /****************************************************************************
778  schannel specific sign/seal.
779  ****************************************************************************/
780
781 static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
782                                 prs_struct *current_pdu,
783                                 uint8 *p_ss_padding_len)
784 {
785         RPC_HDR_AUTH auth_info;
786         uint32 auth_len = prhdr->auth_len;
787         uint32 save_offset = prs_offset(current_pdu);
788         struct schannel_state *schannel_auth =
789                 cli->auth->a_u.schannel_auth;
790         uint8_t *data;
791         uint32 data_len;
792         DATA_BLOB blob;
793         NTSTATUS status;
794
795         if (cli->auth->auth_level == DCERPC_AUTH_LEVEL_NONE
796             || cli->auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
797                 return NT_STATUS_OK;
798         }
799
800         if (auth_len < RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
801                 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len ));
802                 return NT_STATUS_INVALID_PARAMETER;
803         }
804
805         if (!schannel_auth) {
806                 return NT_STATUS_INVALID_PARAMETER;
807         }
808
809         /* Ensure there's enough data for an authenticated response. */
810         if ((auth_len > RPC_MAX_PDU_FRAG_LEN) ||
811                         (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
812                 DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n",
813                         (unsigned int)auth_len ));
814                 return NT_STATUS_INVALID_PARAMETER;
815         }
816
817         data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;
818
819         /* Pull the auth header and the following data into a blob. */
820         /* NB. The offset of the auth_header is relative to the *end*
821          * of the packet, not the start. */
822         if(!prs_set_offset(current_pdu,
823                         prhdr->frag_len - RPC_HDR_AUTH_LEN - auth_len)) {
824                 DEBUG(0,("cli_pipe_verify_schannel: cannot move "
825                         "offset to %u.\n",
826                         (unsigned int)(prhdr->frag_len -
827                                 RPC_HDR_AUTH_LEN - auth_len) ));
828                 return NT_STATUS_BUFFER_TOO_SMALL;
829         }
830
831         if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
832                 DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n"));
833                 return NT_STATUS_BUFFER_TOO_SMALL;
834         }
835
836         /* Ensure auth_pad_len fits into the packet. */
837         if (RPC_HEADER_LEN + RPC_HDR_REQ_LEN + auth_info.auth_pad_len +
838                         RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len) {
839                 DEBUG(0,("cli_pipe_verify_schannel: auth_info.auth_pad_len "
840                         "too large (%u), auth_len (%u), frag_len = (%u).\n",
841                         (unsigned int)auth_info.auth_pad_len,
842                         (unsigned int)auth_len,
843                         (unsigned int)prhdr->frag_len ));
844                 return NT_STATUS_BUFFER_TOO_SMALL;
845         }
846
847         if (auth_info.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
848                 DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n",
849                         auth_info.auth_type));
850                 return NT_STATUS_BUFFER_TOO_SMALL;
851         }
852
853         blob = data_blob_const(prs_data_p(current_pdu) + prs_offset(current_pdu), auth_len);
854
855         if (DEBUGLEVEL >= 10) {
856                 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
857         }
858
859         data = (uint8_t *)prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN;
860
861         switch (cli->auth->auth_level) {
862         case DCERPC_AUTH_LEVEL_PRIVACY:
863                 status = netsec_incoming_packet(schannel_auth,
864                                                 talloc_tos(),
865                                                 true,
866                                                 data,
867                                                 data_len,
868                                                 &blob);
869                 break;
870         case DCERPC_AUTH_LEVEL_INTEGRITY:
871                 status = netsec_incoming_packet(schannel_auth,
872                                                 talloc_tos(),
873                                                 false,
874                                                 data,
875                                                 data_len,
876                                                 &blob);
877                 break;
878         default:
879                 status = NT_STATUS_INTERNAL_ERROR;
880                 break;
881         }
882
883         if (!NT_STATUS_IS_OK(status)) {
884                 DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
885                                 "Connection to %s (%s).\n",
886                                 rpccli_pipe_txt(talloc_tos(), cli),
887                                 nt_errstr(status)));
888                 return NT_STATUS_INVALID_PARAMETER;
889         }
890
891         /*
892          * Return the current pointer to the data offset.
893          */
894
895         if(!prs_set_offset(current_pdu, save_offset)) {
896                 DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
897                         (unsigned int)save_offset ));
898                 return NT_STATUS_BUFFER_TOO_SMALL;
899         }
900
901         /*
902          * Remember the padding length. We must remove it from the real data
903          * stream once the sign/seal is done.
904          */
905
906         *p_ss_padding_len = auth_info.auth_pad_len;
907
908         return NT_STATUS_OK;
909 }
910
911 /****************************************************************************
912  Do the authentication checks on an incoming pdu. Check sign and unseal etc.
913  ****************************************************************************/
914
915 static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
916                                 prs_struct *current_pdu,
917                                 uint8 *p_ss_padding_len)
918 {
919         NTSTATUS ret = NT_STATUS_OK;
920
921         /* Paranioa checks for auth_len. */
922         if (prhdr->auth_len) {
923                 if (prhdr->auth_len > prhdr->frag_len) {
924                         return NT_STATUS_INVALID_PARAMETER;
925                 }
926
927                 if (prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < prhdr->auth_len ||
928                                 prhdr->auth_len + (unsigned int)RPC_HDR_AUTH_LEN < (unsigned int)RPC_HDR_AUTH_LEN) {
929                         /* Integer wrap attempt. */
930                         return NT_STATUS_INVALID_PARAMETER;
931                 }
932         }
933
934         /*
935          * Now we have a complete RPC request PDU fragment, try and verify any auth data.
936          */
937
938         switch(cli->auth->auth_type) {
939                 case PIPE_AUTH_TYPE_NONE:
940                         if (prhdr->auth_len) {
941                                 DEBUG(3, ("cli_pipe_validate_rpc_response: "
942                                           "Connection to %s - got non-zero "
943                                           "auth len %u.\n",
944                                         rpccli_pipe_txt(talloc_tos(), cli),
945                                         (unsigned int)prhdr->auth_len ));
946                                 return NT_STATUS_INVALID_PARAMETER;
947                         }
948                         break;
949
950                 case PIPE_AUTH_TYPE_NTLMSSP:
951                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
952                         ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len);
953                         if (!NT_STATUS_IS_OK(ret)) {
954                                 return ret;
955                         }
956                         break;
957
958                 case PIPE_AUTH_TYPE_SCHANNEL:
959                         ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len);
960                         if (!NT_STATUS_IS_OK(ret)) {
961                                 return ret;
962                         }
963                         break;
964
965                 case PIPE_AUTH_TYPE_KRB5:
966                 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
967                 default:
968                         DEBUG(3, ("cli_pipe_validate_rpc_response: Connection "
969                                   "to %s - unknown internal auth type %u.\n",
970                                   rpccli_pipe_txt(talloc_tos(), cli),
971                                   cli->auth->auth_type ));
972                         return NT_STATUS_INVALID_INFO_CLASS;
973         }
974
975         return NT_STATUS_OK;
976 }
977
978 /****************************************************************************
979  Do basic authentication checks on an incoming pdu.
980  ****************************************************************************/
981
982 static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
983                         prs_struct *current_pdu,
984                         uint8 expected_pkt_type,
985                         char **ppdata,
986                         uint32 *pdata_len,
987                         prs_struct *return_data)
988 {
989
990         NTSTATUS ret = NT_STATUS_OK;
991         uint32 current_pdu_len = prs_data_size(current_pdu);
992
993         if (current_pdu_len != prhdr->frag_len) {
994                 DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n",
995                         (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_len ));
996                 return NT_STATUS_INVALID_PARAMETER;
997         }
998
999         /*
1000          * Point the return values at the real data including the RPC
1001          * header. Just in case the caller wants it.
1002          */
1003         *ppdata = prs_data_p(current_pdu);
1004         *pdata_len = current_pdu_len;
1005
1006         /* Ensure we have the correct type. */
1007         switch (prhdr->pkt_type) {
1008                 case DCERPC_PKT_ALTER_RESP:
1009                 case DCERPC_PKT_BIND_ACK:
1010
1011                         /* Alter context and bind ack share the same packet definitions. */
1012                         break;
1013
1014
1015                 case DCERPC_PKT_RESPONSE:
1016                 {
1017                         RPC_HDR_RESP rhdr_resp;
1018                         uint8 ss_padding_len = 0;
1019
1020                         if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
1021                                 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
1022                                 return NT_STATUS_BUFFER_TOO_SMALL;
1023                         }
1024
1025                         /* Here's where we deal with incoming sign/seal. */
1026                         ret = cli_pipe_validate_rpc_response(cli, prhdr,
1027                                         current_pdu, &ss_padding_len);
1028                         if (!NT_STATUS_IS_OK(ret)) {
1029                                 return ret;
1030                         }
1031
1032                         /* Point the return values at the NDR data. Remember to remove any ss padding. */
1033                         *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
1034
1035                         if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) {
1036                                 return NT_STATUS_BUFFER_TOO_SMALL;
1037                         }
1038
1039                         *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len;
1040
1041                         /* Remember to remove the auth footer. */
1042                         if (prhdr->auth_len) {
1043                                 /* We've already done integer wrap tests on auth_len in
1044                                         cli_pipe_validate_rpc_response(). */
1045                                 if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_len) {
1046                                         return NT_STATUS_BUFFER_TOO_SMALL;
1047                                 }
1048                                 *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len);
1049                         }
1050
1051                         DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n",
1052                                 current_pdu_len, *pdata_len, ss_padding_len ));
1053
1054                         /*
1055                          * If this is the first reply, and the allocation hint is reasonably, try and
1056                          * set up the return_data parse_struct to the correct size.
1057                          */
1058
1059                         if ((prs_data_size(return_data) == 0) && rhdr_resp.alloc_hint && (rhdr_resp.alloc_hint < 15*1024*1024)) {
1060                                 if (!prs_set_buffer_size(return_data, rhdr_resp.alloc_hint)) {
1061                                         DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u "
1062                                                 "too large to allocate\n",
1063                                                 (unsigned int)rhdr_resp.alloc_hint ));
1064                                         return NT_STATUS_NO_MEMORY;
1065                                 }
1066                         }
1067
1068                         break;
1069                 }
1070
1071                 case DCERPC_PKT_BIND_NAK:
1072                         DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK "
1073                                   "received from %s!\n",
1074                                   rpccli_pipe_txt(talloc_tos(), cli)));
1075                         /* Use this for now... */
1076                         return NT_STATUS_NETWORK_ACCESS_DENIED;
1077
1078                 case DCERPC_PKT_FAULT:
1079                 {
1080                         RPC_HDR_RESP rhdr_resp;
1081                         RPC_HDR_FAULT fault_resp;
1082
1083                         if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
1084                                 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
1085                                 return NT_STATUS_BUFFER_TOO_SMALL;
1086                         }
1087
1088                         if(!smb_io_rpc_hdr_fault("fault", &fault_resp, current_pdu, 0)) {
1089                                 DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n"));
1090                                 return NT_STATUS_BUFFER_TOO_SMALL;
1091                         }
1092
1093                         DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1094                                   "code %s received from %s!\n",
1095                                 dcerpc_errstr(talloc_tos(), NT_STATUS_V(fault_resp.status)),
1096                                 rpccli_pipe_txt(talloc_tos(), cli)));
1097                         if (NT_STATUS_IS_OK(fault_resp.status)) {
1098                                 return NT_STATUS_UNSUCCESSFUL;
1099                         } else {
1100                                 return fault_resp.status;
1101                         }
1102                 }
1103
1104                 default:
1105                         DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
1106                                 "from %s!\n",
1107                                 (unsigned int)prhdr->pkt_type,
1108                                 rpccli_pipe_txt(talloc_tos(), cli)));
1109                         return NT_STATUS_INVALID_INFO_CLASS;
1110         }
1111
1112         if (prhdr->pkt_type != expected_pkt_type) {
1113                 DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to %s "
1114                           "got an unexpected RPC packet type - %u, not %u\n",
1115                         rpccli_pipe_txt(talloc_tos(), cli),
1116                         prhdr->pkt_type,
1117                         expected_pkt_type));
1118                 return NT_STATUS_INVALID_INFO_CLASS;
1119         }
1120
1121         /* Do this just before return - we don't want to modify any rpc header
1122            data before now as we may have needed to do cryptographic actions on
1123            it before. */
1124
1125         if ((prhdr->pkt_type == DCERPC_PKT_BIND_ACK) && !(prhdr->flags & DCERPC_PFC_FLAG_LAST)) {
1126                 DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
1127                         "setting fragment first/last ON.\n"));
1128                 prhdr->flags |= DCERPC_PFC_FLAG_FIRST|DCERPC_PFC_FLAG_LAST;
1129         }
1130
1131         return NT_STATUS_OK;
1132 }
1133
1134 /****************************************************************************
1135  Ensure we eat the just processed pdu from the current_pdu prs_struct.
1136  Normally the frag_len and buffer size will match, but on the first trans
1137  reply there is a theoretical chance that buffer size > frag_len, so we must
1138  deal with that.
1139  ****************************************************************************/
1140
1141 static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
1142 {
1143         uint32 current_pdu_len = prs_data_size(current_pdu);
1144
1145         if (current_pdu_len < prhdr->frag_len) {
1146                 return NT_STATUS_BUFFER_TOO_SMALL;
1147         }
1148
1149         /* Common case. */
1150         if (current_pdu_len == (uint32)prhdr->frag_len) {
1151                 prs_mem_free(current_pdu);
1152                 prs_init_empty(current_pdu, prs_get_mem_context(current_pdu), UNMARSHALL);
1153                 /* Make current_pdu dynamic with no memory. */
1154                 prs_give_memory(current_pdu, 0, 0, True);
1155                 return NT_STATUS_OK;
1156         }
1157
1158         /*
1159          * Oh no ! More data in buffer than we processed in current pdu.
1160          * Cheat. Move the data down and shrink the buffer.
1161          */
1162
1163         memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len,
1164                         current_pdu_len - prhdr->frag_len);
1165
1166         /* Remember to set the read offset back to zero. */
1167         prs_set_offset(current_pdu, 0);
1168
1169         /* Shrink the buffer. */
1170         if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) {
1171                 return NT_STATUS_BUFFER_TOO_SMALL;
1172         }
1173
1174         return NT_STATUS_OK;
1175 }
1176
1177 /****************************************************************************
1178  Call a remote api on an arbitrary pipe.  takes param, data and setup buffers.
1179 ****************************************************************************/
1180
1181 struct cli_api_pipe_state {
1182         struct event_context *ev;
1183         struct rpc_cli_transport *transport;
1184         uint8_t *rdata;
1185         uint32_t rdata_len;
1186 };
1187
1188 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
1189 static void cli_api_pipe_write_done(struct tevent_req *subreq);
1190 static void cli_api_pipe_read_done(struct tevent_req *subreq);
1191
1192 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
1193                                             struct event_context *ev,
1194                                             struct rpc_cli_transport *transport,
1195                                             uint8_t *data, size_t data_len,
1196                                             uint32_t max_rdata_len)
1197 {
1198         struct tevent_req *req, *subreq;
1199         struct cli_api_pipe_state *state;
1200         NTSTATUS status;
1201
1202         req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
1203         if (req == NULL) {
1204                 return NULL;
1205         }
1206         state->ev = ev;
1207         state->transport = transport;
1208
1209         if (max_rdata_len < RPC_HEADER_LEN) {
1210                 /*
1211                  * For a RPC reply we always need at least RPC_HEADER_LEN
1212                  * bytes. We check this here because we will receive
1213                  * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
1214                  */
1215                 status = NT_STATUS_INVALID_PARAMETER;
1216                 goto post_status;
1217         }
1218
1219         if (transport->trans_send != NULL) {
1220                 subreq = transport->trans_send(state, ev, data, data_len,
1221                                                max_rdata_len, transport->priv);
1222                 if (subreq == NULL) {
1223                         goto fail;
1224                 }
1225                 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
1226                 return req;
1227         }
1228
1229         /*
1230          * If the transport does not provide a "trans" routine, i.e. for
1231          * example the ncacn_ip_tcp transport, do the write/read step here.
1232          */
1233
1234         subreq = rpc_write_send(state, ev, transport, data, data_len);
1235         if (subreq == NULL) {
1236                 goto fail;
1237         }
1238         tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
1239         return req;
1240
1241         status = NT_STATUS_INVALID_PARAMETER;
1242
1243  post_status:
1244         tevent_req_nterror(req, status);
1245         return tevent_req_post(req, ev);
1246  fail:
1247         TALLOC_FREE(req);
1248         return NULL;
1249 }
1250
1251 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
1252 {
1253         struct tevent_req *req = tevent_req_callback_data(
1254                 subreq, struct tevent_req);
1255         struct cli_api_pipe_state *state = tevent_req_data(
1256                 req, struct cli_api_pipe_state);
1257         NTSTATUS status;
1258
1259         status = state->transport->trans_recv(subreq, state, &state->rdata,
1260                                               &state->rdata_len);
1261         TALLOC_FREE(subreq);
1262         if (!NT_STATUS_IS_OK(status)) {
1263                 tevent_req_nterror(req, status);
1264                 return;
1265         }
1266         tevent_req_done(req);
1267 }
1268
1269 static void cli_api_pipe_write_done(struct tevent_req *subreq)
1270 {
1271         struct tevent_req *req = tevent_req_callback_data(
1272                 subreq, struct tevent_req);
1273         struct cli_api_pipe_state *state = tevent_req_data(
1274                 req, struct cli_api_pipe_state);
1275         NTSTATUS status;
1276
1277         status = rpc_write_recv(subreq);
1278         TALLOC_FREE(subreq);
1279         if (!NT_STATUS_IS_OK(status)) {
1280                 tevent_req_nterror(req, status);
1281                 return;
1282         }
1283
1284         state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN);
1285         if (tevent_req_nomem(state->rdata, req)) {
1286                 return;
1287         }
1288
1289         /*
1290          * We don't need to use rpc_read_send here, the upper layer will cope
1291          * with a short read, transport->trans_send could also return less
1292          * than state->max_rdata_len.
1293          */
1294         subreq = state->transport->read_send(state, state->ev, state->rdata,
1295                                              RPC_HEADER_LEN,
1296                                              state->transport->priv);
1297         if (tevent_req_nomem(subreq, req)) {
1298                 return;
1299         }
1300         tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
1301 }
1302
1303 static void cli_api_pipe_read_done(struct tevent_req *subreq)
1304 {
1305         struct tevent_req *req = tevent_req_callback_data(
1306                 subreq, struct tevent_req);
1307         struct cli_api_pipe_state *state = tevent_req_data(
1308                 req, struct cli_api_pipe_state);
1309         NTSTATUS status;
1310         ssize_t received;
1311
1312         status = state->transport->read_recv(subreq, &received);
1313         TALLOC_FREE(subreq);
1314         if (!NT_STATUS_IS_OK(status)) {
1315                 tevent_req_nterror(req, status);
1316                 return;
1317         }
1318         state->rdata_len = received;
1319         tevent_req_done(req);
1320 }
1321
1322 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1323                                   uint8_t **prdata, uint32_t *prdata_len)
1324 {
1325         struct cli_api_pipe_state *state = tevent_req_data(
1326                 req, struct cli_api_pipe_state);
1327         NTSTATUS status;
1328
1329         if (tevent_req_is_nterror(req, &status)) {
1330                 return status;
1331         }
1332
1333         *prdata = talloc_move(mem_ctx, &state->rdata);
1334         *prdata_len = state->rdata_len;
1335         return NT_STATUS_OK;
1336 }
1337
1338 /****************************************************************************
1339  Send data on an rpc pipe via trans. The prs_struct data must be the last
1340  pdu fragment of an NDR data stream.
1341
1342  Receive response data from an rpc pipe, which may be large...
1343
1344  Read the first fragment: unfortunately have to use SMBtrans for the first
1345  bit, then SMBreadX for subsequent bits.
1346
1347  If first fragment received also wasn't the last fragment, continue
1348  getting fragments until we _do_ receive the last fragment.
1349
1350  Request/Response PDU's look like the following...
1351
1352  |<------------------PDU len----------------------------------------------->|
1353  |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
1354
1355  +------------+-----------------+-------------+---------------+-------------+
1356  | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR      | AUTH DATA   |
1357  +------------+-----------------+-------------+---------------+-------------+
1358
1359  Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
1360  signing & sealing being negotiated.
1361
1362  ****************************************************************************/
1363
1364 struct rpc_api_pipe_state {
1365         struct event_context *ev;
1366         struct rpc_pipe_client *cli;
1367         uint8_t expected_pkt_type;
1368
1369         prs_struct incoming_frag;
1370         struct rpc_hdr_info rhdr;
1371
1372         prs_struct incoming_pdu;        /* Incoming reply */
1373         uint32_t incoming_pdu_offset;
1374 };
1375
1376 static int rpc_api_pipe_state_destructor(struct rpc_api_pipe_state *state)
1377 {
1378         prs_mem_free(&state->incoming_frag);
1379         prs_mem_free(&state->incoming_pdu);
1380         return 0;
1381 }
1382
1383 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
1384 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
1385
1386 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
1387                                             struct event_context *ev,
1388                                             struct rpc_pipe_client *cli,
1389                                             prs_struct *data, /* Outgoing PDU */
1390                                             uint8_t expected_pkt_type)
1391 {
1392         struct tevent_req *req, *subreq;
1393         struct rpc_api_pipe_state *state;
1394         uint16_t max_recv_frag;
1395         NTSTATUS status;
1396
1397         req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
1398         if (req == NULL) {
1399                 return NULL;
1400         }
1401         state->ev = ev;
1402         state->cli = cli;
1403         state->expected_pkt_type = expected_pkt_type;
1404         state->incoming_pdu_offset = 0;
1405
1406         prs_init_empty(&state->incoming_frag, state, UNMARSHALL);
1407
1408         prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
1409         /* Make incoming_pdu dynamic with no memory. */
1410         prs_give_memory(&state->incoming_pdu, NULL, 0, true);
1411
1412         talloc_set_destructor(state, rpc_api_pipe_state_destructor);
1413
1414         /*
1415          * Ensure we're not sending too much.
1416          */
1417         if (prs_offset(data) > cli->max_xmit_frag) {
1418                 status = NT_STATUS_INVALID_PARAMETER;
1419                 goto post_status;
1420         }
1421
1422         DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
1423
1424         max_recv_frag = cli->max_recv_frag;
1425
1426 #if 0
1427         max_recv_frag = RPC_HEADER_LEN + 10 + (sys_random() % 32);
1428 #endif
1429
1430         subreq = cli_api_pipe_send(state, ev, cli->transport,
1431                                    (uint8_t *)prs_data_p(data),
1432                                    prs_offset(data), max_recv_frag);
1433         if (subreq == NULL) {
1434                 goto fail;
1435         }
1436         tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
1437         return req;
1438
1439  post_status:
1440         tevent_req_nterror(req, status);
1441         return tevent_req_post(req, ev);
1442  fail:
1443         TALLOC_FREE(req);
1444         return NULL;
1445 }
1446
1447 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
1448 {
1449         struct tevent_req *req = tevent_req_callback_data(
1450                 subreq, struct tevent_req);
1451         struct rpc_api_pipe_state *state = tevent_req_data(
1452                 req, struct rpc_api_pipe_state);
1453         NTSTATUS status;
1454         uint8_t *rdata = NULL;
1455         uint32_t rdata_len = 0;
1456
1457         status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
1458         TALLOC_FREE(subreq);
1459         if (!NT_STATUS_IS_OK(status)) {
1460                 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
1461                 tevent_req_nterror(req, status);
1462                 return;
1463         }
1464
1465         if (rdata == NULL) {
1466                 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
1467                          rpccli_pipe_txt(talloc_tos(), state->cli)));
1468                 tevent_req_done(req);
1469                 return;
1470         }
1471
1472         /*
1473          * This is equivalent to a talloc_steal - gives rdata to
1474          * the prs_struct state->incoming_frag.
1475          */
1476         prs_give_memory(&state->incoming_frag, (char *)rdata, rdata_len, true);
1477         rdata = NULL;
1478
1479         /* Ensure we have enough data for a pdu. */
1480         subreq = get_complete_frag_send(state, state->ev, state->cli,
1481                                         &state->rhdr, &state->incoming_frag);
1482         if (tevent_req_nomem(subreq, req)) {
1483                 return;
1484         }
1485         tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1486 }
1487
1488 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
1489 {
1490         struct tevent_req *req = tevent_req_callback_data(
1491                 subreq, struct tevent_req);
1492         struct rpc_api_pipe_state *state = tevent_req_data(
1493                 req, struct rpc_api_pipe_state);
1494         NTSTATUS status;
1495         char *rdata = NULL;
1496         uint32_t rdata_len = 0;
1497
1498         status = get_complete_frag_recv(subreq);
1499         TALLOC_FREE(subreq);
1500         if (!NT_STATUS_IS_OK(status)) {
1501                 DEBUG(5, ("get_complete_frag failed: %s\n",
1502                           nt_errstr(status)));
1503                 tevent_req_nterror(req, status);
1504                 return;
1505         }
1506
1507         status = cli_pipe_validate_current_pdu(
1508                 state->cli, &state->rhdr, &state->incoming_frag,
1509                 state->expected_pkt_type, &rdata, &rdata_len,
1510                 &state->incoming_pdu);
1511
1512         DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
1513                   (unsigned)prs_data_size(&state->incoming_frag),
1514                   (unsigned)state->incoming_pdu_offset,
1515                   nt_errstr(status)));
1516
1517         if (!NT_STATUS_IS_OK(status)) {
1518                 tevent_req_nterror(req, status);
1519                 return;
1520         }
1521
1522         if ((state->rhdr.flags & DCERPC_PFC_FLAG_FIRST)
1523             && (state->rhdr.pack_type[0] == 0)) {
1524                 /*
1525                  * Set the data type correctly for big-endian data on the
1526                  * first packet.
1527                  */
1528                 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1529                           "big-endian.\n",
1530                           rpccli_pipe_txt(talloc_tos(), state->cli)));
1531                 prs_set_endian_data(&state->incoming_pdu, RPC_BIG_ENDIAN);
1532         }
1533         /*
1534          * Check endianness on subsequent packets.
1535          */
1536         if (state->incoming_frag.bigendian_data
1537             != state->incoming_pdu.bigendian_data) {
1538                 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1539                          "%s\n",
1540                          state->incoming_pdu.bigendian_data?"big":"little",
1541                          state->incoming_frag.bigendian_data?"big":"little"));
1542                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1543                 return;
1544         }
1545
1546         /* Now copy the data portion out of the pdu into rbuf. */
1547         if (!prs_force_grow(&state->incoming_pdu, rdata_len)) {
1548                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1549                 return;
1550         }
1551
1552         memcpy(prs_data_p(&state->incoming_pdu) + state->incoming_pdu_offset,
1553                rdata, (size_t)rdata_len);
1554         state->incoming_pdu_offset += rdata_len;
1555
1556         status = cli_pipe_reset_current_pdu(state->cli, &state->rhdr,
1557                                             &state->incoming_frag);
1558         if (!NT_STATUS_IS_OK(status)) {
1559                 tevent_req_nterror(req, status);
1560                 return;
1561         }
1562
1563         if (state->rhdr.flags & DCERPC_PFC_FLAG_LAST) {
1564                 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1565                           rpccli_pipe_txt(talloc_tos(), state->cli),
1566                           (unsigned)prs_data_size(&state->incoming_pdu)));
1567                 tevent_req_done(req);
1568                 return;
1569         }
1570
1571         subreq = get_complete_frag_send(state, state->ev, state->cli,
1572                                         &state->rhdr, &state->incoming_frag);
1573         if (tevent_req_nomem(subreq, req)) {
1574                 return;
1575         }
1576         tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1577 }
1578
1579 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1580                                   prs_struct *reply_pdu)
1581 {
1582         struct rpc_api_pipe_state *state = tevent_req_data(
1583                 req, struct rpc_api_pipe_state);
1584         NTSTATUS status;
1585
1586         if (tevent_req_is_nterror(req, &status)) {
1587                 return status;
1588         }
1589
1590         *reply_pdu = state->incoming_pdu;
1591         reply_pdu->mem_ctx = mem_ctx;
1592
1593         /*
1594          * Prevent state->incoming_pdu from being freed
1595          * when state is freed.
1596          */
1597         talloc_steal(mem_ctx, prs_data_p(reply_pdu));
1598         prs_init_empty(&state->incoming_pdu, state, UNMARSHALL);
1599
1600         return NT_STATUS_OK;
1601 }
1602
1603 /*******************************************************************
1604  Creates krb5 auth bind.
1605  ********************************************************************/
1606
1607 static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
1608                                                 enum dcerpc_AuthLevel auth_level,
1609                                                 RPC_HDR_AUTH *pauth_out,
1610                                                 prs_struct *auth_data)
1611 {
1612 #ifdef HAVE_KRB5
1613         int ret;
1614         struct kerberos_auth_struct *a = cli->auth->a_u.kerberos_auth;
1615         DATA_BLOB tkt = data_blob_null;
1616         DATA_BLOB tkt_wrapped = data_blob_null;
1617
1618         /* We may change the pad length before marshalling. */
1619         init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_KRB5, (int)auth_level, 0, 1);
1620
1621         DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
1622                 a->service_principal ));
1623
1624         /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
1625
1626         ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
1627                         &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, NULL);
1628
1629         if (ret) {
1630                 DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
1631                         "failed with %s\n",
1632                         a->service_principal,
1633                         error_message(ret) ));
1634
1635                 data_blob_free(&tkt);
1636                 prs_mem_free(auth_data);
1637                 return NT_STATUS_INVALID_PARAMETER;
1638         }
1639
1640         /* wrap that up in a nice GSS-API wrapping */
1641         tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
1642
1643         data_blob_free(&tkt);
1644
1645         /* Auth len in the rpc header doesn't include auth_header. */
1646         if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) {
1647                 data_blob_free(&tkt_wrapped);
1648                 prs_mem_free(auth_data);
1649                 return NT_STATUS_NO_MEMORY;
1650         }
1651
1652         DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
1653         dump_data(5, tkt_wrapped.data, tkt_wrapped.length);
1654
1655         data_blob_free(&tkt_wrapped);
1656         return NT_STATUS_OK;
1657 #else
1658         return NT_STATUS_INVALID_PARAMETER;
1659 #endif
1660 }
1661
1662 /*******************************************************************
1663  Creates SPNEGO NTLMSSP auth bind.
1664  ********************************************************************/
1665
1666 static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1667                                                 enum dcerpc_AuthLevel auth_level,
1668                                                 RPC_HDR_AUTH *pauth_out,
1669                                                 prs_struct *auth_data)
1670 {
1671         NTSTATUS nt_status;
1672         DATA_BLOB null_blob = data_blob_null;
1673         DATA_BLOB request = data_blob_null;
1674         DATA_BLOB spnego_msg = data_blob_null;
1675
1676         /* We may change the pad length before marshalling. */
1677         init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_SPNEGO, (int)auth_level, 0, 1);
1678
1679         DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1680         nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1681                                         null_blob,
1682                                         &request);
1683
1684         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1685                 data_blob_free(&request);
1686                 prs_mem_free(auth_data);
1687                 return nt_status;
1688         }
1689
1690         /* Wrap this in SPNEGO. */
1691         spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
1692
1693         data_blob_free(&request);
1694
1695         /* Auth len in the rpc header doesn't include auth_header. */
1696         if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) {
1697                 data_blob_free(&spnego_msg);
1698                 prs_mem_free(auth_data);
1699                 return NT_STATUS_NO_MEMORY;
1700         }
1701
1702         DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1703         dump_data(5, spnego_msg.data, spnego_msg.length);
1704
1705         data_blob_free(&spnego_msg);
1706         return NT_STATUS_OK;
1707 }
1708
1709 /*******************************************************************
1710  Creates NTLMSSP auth bind.
1711  ********************************************************************/
1712
1713 static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1714                                                 enum dcerpc_AuthLevel auth_level,
1715                                                 RPC_HDR_AUTH *pauth_out,
1716                                                 prs_struct *auth_data)
1717 {
1718         NTSTATUS nt_status;
1719         DATA_BLOB null_blob = data_blob_null;
1720         DATA_BLOB request = data_blob_null;
1721
1722         /* We may change the pad length before marshalling. */
1723         init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_NTLMSSP, (int)auth_level, 0, 1);
1724
1725         DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1726         nt_status = ntlmssp_update(cli->auth->a_u.ntlmssp_state,
1727                                         null_blob,
1728                                         &request);
1729
1730         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1731                 data_blob_free(&request);
1732                 prs_mem_free(auth_data);
1733                 return nt_status;
1734         }
1735
1736         /* Auth len in the rpc header doesn't include auth_header. */
1737         if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) {
1738                 data_blob_free(&request);
1739                 prs_mem_free(auth_data);
1740                 return NT_STATUS_NO_MEMORY;
1741         }
1742
1743         DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1744         dump_data(5, request.data, request.length);
1745
1746         data_blob_free(&request);
1747         return NT_STATUS_OK;
1748 }
1749
1750 /*******************************************************************
1751  Creates schannel auth bind.
1752  ********************************************************************/
1753
1754 static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
1755                                                 enum dcerpc_AuthLevel auth_level,
1756                                                 RPC_HDR_AUTH *pauth_out,
1757                                                 prs_struct *auth_data)
1758 {
1759         struct NL_AUTH_MESSAGE r;
1760         enum ndr_err_code ndr_err;
1761         DATA_BLOB blob;
1762
1763         /* We may change the pad length before marshalling. */
1764         init_rpc_hdr_auth(pauth_out, DCERPC_AUTH_TYPE_SCHANNEL, (int)auth_level, 0, 1);
1765
1766         /* Use lp_workgroup() if domain not specified */
1767
1768         if (!cli->auth->domain || !cli->auth->domain[0]) {
1769                 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1770                 if (cli->auth->domain == NULL) {
1771                         return NT_STATUS_NO_MEMORY;
1772                 }
1773         }
1774
1775         /*
1776          * Now marshall the data into the auth parse_struct.
1777          */
1778
1779         r.MessageType                   = NL_NEGOTIATE_REQUEST;
1780         r.Flags                         = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1781                                           NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1782         r.oem_netbios_domain.a          = cli->auth->domain;
1783         r.oem_netbios_computer.a        = global_myname();
1784
1785         ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &r,
1786                        (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
1787         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1788                 DEBUG(0,("Failed to marshall NL_AUTH_MESSAGE.\n"));
1789                 prs_mem_free(auth_data);
1790                 return ndr_map_error2ntstatus(ndr_err);
1791         }
1792
1793         if (DEBUGLEVEL >= 10) {
1794                 NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, &r);
1795         }
1796
1797         if (!prs_copy_data_in(auth_data, (const char *)blob.data, blob.length))
1798         {
1799                 prs_mem_free(auth_data);
1800                 return NT_STATUS_NO_MEMORY;
1801         }
1802
1803         return NT_STATUS_OK;
1804 }
1805
1806 /*******************************************************************
1807  Creates the internals of a DCE/RPC bind request or alter context PDU.
1808  ********************************************************************/
1809
1810 static NTSTATUS create_bind_or_alt_ctx_internal(enum dcerpc_pkt_type pkt_type,
1811                                                 prs_struct *rpc_out, 
1812                                                 uint32 rpc_call_id,
1813                                                 const struct ndr_syntax_id *abstract,
1814                                                 const struct ndr_syntax_id *transfer,
1815                                                 RPC_HDR_AUTH *phdr_auth,
1816                                                 prs_struct *pauth_info)
1817 {
1818         RPC_HDR hdr;
1819         RPC_HDR_RB hdr_rb;
1820         RPC_CONTEXT rpc_ctx;
1821         uint16 auth_len = prs_offset(pauth_info);
1822         uint8 ss_padding_len = 0;
1823         uint16 frag_len = 0;
1824
1825         /* create the RPC context. */
1826         init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);
1827
1828         /* create the bind request RPC_HDR_RB */
1829         init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
1830
1831         /* Start building the frag length. */
1832         frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1833
1834         /* Do we need to pad ? */
1835         if (auth_len) {
1836                 uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
1837                 if (data_len % CLIENT_NDR_PADDING_SIZE) {
1838                         ss_padding_len = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
1839                         phdr_auth->auth_pad_len = ss_padding_len;
1840                 }
1841                 frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;
1842         }
1843
1844         /* Create the request RPC_HDR */
1845         init_rpc_hdr(&hdr, pkt_type, DCERPC_PFC_FLAG_FIRST|DCERPC_PFC_FLAG_LAST, rpc_call_id, frag_len, auth_len);
1846
1847         /* Marshall the RPC header */
1848         if(!smb_io_rpc_hdr("hdr"   , &hdr, rpc_out, 0)) {
1849                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
1850                 return NT_STATUS_NO_MEMORY;
1851         }
1852
1853         /* Marshall the bind request data */
1854         if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
1855                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1856                 return NT_STATUS_NO_MEMORY;
1857         }
1858
1859         /*
1860          * Grow the outgoing buffer to store any auth info.
1861          */
1862
1863         if(auth_len != 0) {
1864                 if (ss_padding_len) {
1865                         char pad[CLIENT_NDR_PADDING_SIZE];
1866                         memset(pad, '\0', CLIENT_NDR_PADDING_SIZE);
1867                         if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
1868                                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
1869                                 return NT_STATUS_NO_MEMORY;
1870                         }
1871                 }
1872
1873                 if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {
1874                         DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
1875                         return NT_STATUS_NO_MEMORY;
1876                 }
1877
1878
1879                 if(!prs_append_prs_data( rpc_out, pauth_info)) {
1880                         DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
1881                         return NT_STATUS_NO_MEMORY;
1882                 }
1883         }
1884
1885         return NT_STATUS_OK;
1886 }
1887
1888 /*******************************************************************
1889  Creates a DCE/RPC bind request.
1890  ********************************************************************/
1891
1892 static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
1893                                 prs_struct *rpc_out, 
1894                                 uint32 rpc_call_id,
1895                                 const struct ndr_syntax_id *abstract,
1896                                 const struct ndr_syntax_id *transfer,
1897                                 enum pipe_auth_type auth_type,
1898                                 enum dcerpc_AuthLevel auth_level)
1899 {
1900         RPC_HDR_AUTH hdr_auth;
1901         prs_struct auth_info;
1902         NTSTATUS ret = NT_STATUS_OK;
1903
1904         ZERO_STRUCT(hdr_auth);
1905         if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
1906                 return NT_STATUS_NO_MEMORY;
1907
1908         switch (auth_type) {
1909                 case PIPE_AUTH_TYPE_SCHANNEL:
1910                         ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1911                         if (!NT_STATUS_IS_OK(ret)) {
1912                                 prs_mem_free(&auth_info);
1913                                 return ret;
1914                         }
1915                         break;
1916
1917                 case PIPE_AUTH_TYPE_NTLMSSP:
1918                         ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1919                         if (!NT_STATUS_IS_OK(ret)) {
1920                                 prs_mem_free(&auth_info);
1921                                 return ret;
1922                         }
1923                         break;
1924
1925                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
1926                         ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1927                         if (!NT_STATUS_IS_OK(ret)) {
1928                                 prs_mem_free(&auth_info);
1929                                 return ret;
1930                         }
1931                         break;
1932
1933                 case PIPE_AUTH_TYPE_KRB5:
1934                         ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);
1935                         if (!NT_STATUS_IS_OK(ret)) {
1936                                 prs_mem_free(&auth_info);
1937                                 return ret;
1938                         }
1939                         break;
1940
1941                 case PIPE_AUTH_TYPE_NONE:
1942                         break;
1943
1944                 default:
1945                         /* "Can't" happen. */
1946                         return NT_STATUS_INVALID_INFO_CLASS;
1947         }
1948
1949         ret = create_bind_or_alt_ctx_internal(DCERPC_PKT_BIND,
1950                                                 rpc_out, 
1951                                                 rpc_call_id,
1952                                                 abstract,
1953                                                 transfer,
1954                                                 &hdr_auth,
1955                                                 &auth_info);
1956
1957         prs_mem_free(&auth_info);
1958         return ret;
1959 }
1960
1961 /*******************************************************************
1962  Create and add the NTLMSSP sign/seal auth header and data.
1963  ********************************************************************/
1964
1965 static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
1966                                         RPC_HDR *phdr,
1967                                         uint32 ss_padding_len,
1968                                         prs_struct *outgoing_pdu)
1969 {
1970         RPC_HDR_AUTH auth_info;
1971         NTSTATUS status;
1972         DATA_BLOB auth_blob = data_blob_null;
1973         uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
1974         TALLOC_CTX *frame;
1975
1976         if (!cli->auth->a_u.ntlmssp_state) {
1977                 return NT_STATUS_INVALID_PARAMETER;
1978         }
1979
1980         frame = talloc_stackframe();
1981
1982         /* Init and marshall the auth header. */
1983         init_rpc_hdr_auth(&auth_info,
1984                         map_pipe_auth_type_to_rpc_auth_type(
1985                                 cli->auth->auth_type),
1986                         cli->auth->auth_level,
1987                         ss_padding_len,
1988                         1 /* context id. */);
1989
1990         if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
1991                 DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
1992                 talloc_free(frame);
1993                 return NT_STATUS_NO_MEMORY;
1994         }
1995
1996         switch (cli->auth->auth_level) {
1997                 case DCERPC_AUTH_LEVEL_PRIVACY:
1998                         /* Data portion is encrypted. */
1999                         status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
2000                                                      frame,
2001                                         (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
2002                                         data_and_pad_len,
2003                                         (unsigned char *)prs_data_p(outgoing_pdu),
2004                                         (size_t)prs_offset(outgoing_pdu),
2005                                         &auth_blob);
2006                         if (!NT_STATUS_IS_OK(status)) {
2007                                 talloc_free(frame);
2008                                 return status;
2009                         }
2010                         break;
2011
2012                 case DCERPC_AUTH_LEVEL_INTEGRITY:
2013                         /* Data is signed. */
2014                         status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
2015                                                      frame,
2016                                         (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
2017                                         data_and_pad_len,
2018                                         (unsigned char *)prs_data_p(outgoing_pdu),
2019                                         (size_t)prs_offset(outgoing_pdu),
2020                                         &auth_blob);
2021                         if (!NT_STATUS_IS_OK(status)) {
2022                                 talloc_free(frame);
2023                                 return status;
2024                         }
2025                         break;
2026
2027                 default:
2028                         /* Can't happen. */
2029                         smb_panic("bad auth level");
2030                         /* Notreached. */
2031                         return NT_STATUS_INVALID_PARAMETER;
2032         }
2033
2034         /* Finally marshall the blob. */
2035
2036         if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) {
2037                 DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
2038                         (unsigned int)NTLMSSP_SIG_SIZE));
2039                 talloc_free(frame);
2040                 return NT_STATUS_NO_MEMORY;
2041         }
2042
2043         talloc_free(frame);
2044         return NT_STATUS_OK;
2045 }
2046
2047 /*******************************************************************
2048  Create and add the schannel sign/seal auth header and data.
2049  ********************************************************************/
2050
2051 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
2052                                         RPC_HDR *phdr,
2053                                         uint32 ss_padding_len,
2054                                         prs_struct *outgoing_pdu)
2055 {
2056         RPC_HDR_AUTH auth_info;
2057         struct schannel_state *sas = cli->auth->a_u.schannel_auth;
2058         char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
2059         size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
2060         DATA_BLOB blob;
2061         NTSTATUS status;
2062
2063         if (!sas) {
2064                 return NT_STATUS_INVALID_PARAMETER;
2065         }
2066
2067         /* Init and marshall the auth header. */
2068         init_rpc_hdr_auth(&auth_info,
2069                         map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
2070                         cli->auth->auth_level,
2071                         ss_padding_len,
2072                         1 /* context id. */);
2073
2074         if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
2075                 DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
2076                 return NT_STATUS_NO_MEMORY;
2077         }
2078
2079         DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
2080                         sas->seq_num));
2081
2082         switch (cli->auth->auth_level) {
2083         case DCERPC_AUTH_LEVEL_PRIVACY:
2084                 status = netsec_outgoing_packet(sas,
2085                                                 talloc_tos(),
2086                                                 true,
2087                                                 (uint8_t *)data_p,
2088                                                 data_and_pad_len,
2089                                                 &blob);
2090                 break;
2091         case DCERPC_AUTH_LEVEL_INTEGRITY:
2092                 status = netsec_outgoing_packet(sas,
2093                                                 talloc_tos(),
2094                                                 false,
2095                                                 (uint8_t *)data_p,
2096                                                 data_and_pad_len,
2097                                                 &blob);
2098                 break;
2099         default:
2100                 status = NT_STATUS_INTERNAL_ERROR;
2101                 break;
2102         }
2103
2104         if (!NT_STATUS_IS_OK(status)) {
2105                 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
2106                         nt_errstr(status)));
2107                 return status;
2108         }
2109
2110         if (DEBUGLEVEL >= 10) {
2111                 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
2112         }
2113
2114         /* Finally marshall the blob. */
2115         if (!prs_copy_data_in(outgoing_pdu, (const char *)blob.data, blob.length)) {
2116                 return NT_STATUS_NO_MEMORY;
2117         }
2118
2119         return NT_STATUS_OK;
2120 }
2121
2122 /*******************************************************************
2123  Calculate how much data we're going to send in this packet, also
2124  work out any sign/seal padding length.
2125  ********************************************************************/
2126
2127 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
2128                                         uint32 data_left,
2129                                         uint16 *p_frag_len,
2130                                         uint16 *p_auth_len,
2131                                         uint32 *p_ss_padding)
2132 {
2133         uint32 data_space, data_len;
2134
2135 #if 0
2136         if ((data_left > 0) && (sys_random() % 2)) {
2137                 data_left = MAX(data_left/2, 1);
2138         }
2139 #endif
2140
2141         switch (cli->auth->auth_level) {
2142                 case DCERPC_AUTH_LEVEL_NONE:
2143                 case DCERPC_AUTH_LEVEL_CONNECT:
2144                         data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
2145                         data_len = MIN(data_space, data_left);
2146                         *p_ss_padding = 0;
2147                         *p_auth_len = 0;
2148                         *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
2149                         return data_len;
2150
2151                 case DCERPC_AUTH_LEVEL_INTEGRITY:
2152                 case DCERPC_AUTH_LEVEL_PRIVACY:
2153                         /* Treat the same for all authenticated rpc requests. */
2154                         switch(cli->auth->auth_type) {
2155                                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2156                                 case PIPE_AUTH_TYPE_NTLMSSP:
2157                                         *p_auth_len = NTLMSSP_SIG_SIZE;
2158                                         break;
2159                                 case PIPE_AUTH_TYPE_SCHANNEL:
2160                                         *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
2161                                         break;
2162                                 default:
2163                                         smb_panic("bad auth type");
2164                                         break;
2165                         }
2166
2167                         data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
2168                                                 RPC_HDR_AUTH_LEN - *p_auth_len;
2169
2170                         data_len = MIN(data_space, data_left);
2171                         *p_ss_padding = 0;
2172                         if (data_len % CLIENT_NDR_PADDING_SIZE) {
2173                                 *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
2174                         }
2175                         *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN +                /* Normal headers. */
2176                                         data_len + *p_ss_padding +              /* data plus padding. */
2177                                         RPC_HDR_AUTH_LEN + *p_auth_len;         /* Auth header and auth data. */
2178                         return data_len;
2179
2180                 default:
2181                         smb_panic("bad auth level");
2182                         /* Notreached. */
2183                         return 0;
2184         }
2185 }
2186
2187 /*******************************************************************
2188  External interface.
2189  Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
2190  Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
2191  and deals with signing/sealing details.
2192  ********************************************************************/
2193
2194 struct rpc_api_pipe_req_state {
2195         struct event_context *ev;
2196         struct rpc_pipe_client *cli;
2197         uint8_t op_num;
2198         uint32_t call_id;
2199         prs_struct *req_data;
2200         uint32_t req_data_sent;
2201         prs_struct outgoing_frag;
2202         prs_struct reply_pdu;
2203 };
2204
2205 static int rpc_api_pipe_req_state_destructor(struct rpc_api_pipe_req_state *s)
2206 {
2207         prs_mem_free(&s->outgoing_frag);
2208         prs_mem_free(&s->reply_pdu);
2209         return 0;
2210 }
2211
2212 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
2213 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
2214 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2215                                   bool *is_last_frag);
2216
2217 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
2218                                          struct event_context *ev,
2219                                          struct rpc_pipe_client *cli,
2220                                          uint8_t op_num,
2221                                          prs_struct *req_data)
2222 {
2223         struct tevent_req *req, *subreq;
2224         struct rpc_api_pipe_req_state *state;
2225         NTSTATUS status;
2226         bool is_last_frag;
2227
2228         req = tevent_req_create(mem_ctx, &state,
2229                                 struct rpc_api_pipe_req_state);
2230         if (req == NULL) {
2231                 return NULL;
2232         }
2233         state->ev = ev;
2234         state->cli = cli;
2235         state->op_num = op_num;
2236         state->req_data = req_data;
2237         state->req_data_sent = 0;
2238         state->call_id = get_rpc_call_id();
2239
2240         if (cli->max_xmit_frag
2241             < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
2242                 /* Server is screwed up ! */
2243                 status = NT_STATUS_INVALID_PARAMETER;
2244                 goto post_status;
2245         }
2246
2247         prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2248
2249         if (!prs_init(&state->outgoing_frag, cli->max_xmit_frag,
2250                       state, MARSHALL)) {
2251                 goto fail;
2252         }
2253
2254         talloc_set_destructor(state, rpc_api_pipe_req_state_destructor);
2255
2256         status = prepare_next_frag(state, &is_last_frag);
2257         if (!NT_STATUS_IS_OK(status)) {
2258                 goto post_status;
2259         }
2260
2261         if (is_last_frag) {
2262                 subreq = rpc_api_pipe_send(state, ev, state->cli,
2263                                            &state->outgoing_frag,
2264                                            DCERPC_PKT_RESPONSE);
2265                 if (subreq == NULL) {
2266                         goto fail;
2267                 }
2268                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2269         } else {
2270                 subreq = rpc_write_send(
2271                         state, ev, cli->transport,
2272                         (uint8_t *)prs_data_p(&state->outgoing_frag),
2273                         prs_offset(&state->outgoing_frag));
2274                 if (subreq == NULL) {
2275                         goto fail;
2276                 }
2277                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2278                                         req);
2279         }
2280         return req;
2281
2282  post_status:
2283         tevent_req_nterror(req, status);
2284         return tevent_req_post(req, ev);
2285  fail:
2286         TALLOC_FREE(req);
2287         return NULL;
2288 }
2289
2290 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2291                                   bool *is_last_frag)
2292 {
2293         RPC_HDR hdr;
2294         RPC_HDR_REQ hdr_req;
2295         uint32_t data_sent_thistime;
2296         uint16_t auth_len;
2297         uint16_t frag_len;
2298         uint8_t flags = 0;
2299         uint32_t ss_padding;
2300         uint32_t data_left;
2301         char pad[8] = { 0, };
2302         NTSTATUS status;
2303
2304         data_left = prs_offset(state->req_data) - state->req_data_sent;
2305
2306         data_sent_thistime = calculate_data_len_tosend(
2307                 state->cli, data_left, &frag_len, &auth_len, &ss_padding);
2308
2309         if (state->req_data_sent == 0) {
2310                 flags = DCERPC_PFC_FLAG_FIRST;
2311         }
2312
2313         if (data_sent_thistime == data_left) {
2314                 flags |= DCERPC_PFC_FLAG_LAST;
2315         }
2316
2317         if (!prs_set_offset(&state->outgoing_frag, 0)) {
2318                 return NT_STATUS_NO_MEMORY;
2319         }
2320
2321         /* Create and marshall the header and request header. */
2322         init_rpc_hdr(&hdr, DCERPC_PKT_REQUEST, flags, state->call_id, frag_len,
2323                      auth_len);
2324
2325         if (!smb_io_rpc_hdr("hdr    ", &hdr, &state->outgoing_frag, 0)) {
2326                 return NT_STATUS_NO_MEMORY;
2327         }
2328
2329         /* Create the rpc request RPC_HDR_REQ */
2330         init_rpc_hdr_req(&hdr_req, prs_offset(state->req_data),
2331                          state->op_num);
2332
2333         if (!smb_io_rpc_hdr_req("hdr_req", &hdr_req,
2334                                 &state->outgoing_frag, 0)) {
2335                 return NT_STATUS_NO_MEMORY;
2336         }
2337
2338         /* Copy in the data, plus any ss padding. */
2339         if (!prs_append_some_prs_data(&state->outgoing_frag,
2340                                       state->req_data, state->req_data_sent,
2341                                       data_sent_thistime)) {
2342                 return NT_STATUS_NO_MEMORY;
2343         }
2344
2345         /* Copy the sign/seal padding data. */
2346         if (!prs_copy_data_in(&state->outgoing_frag, pad, ss_padding)) {
2347                 return NT_STATUS_NO_MEMORY;
2348         }
2349
2350         /* Generate any auth sign/seal and add the auth footer. */
2351         switch (state->cli->auth->auth_type) {
2352         case PIPE_AUTH_TYPE_NONE:
2353                 status = NT_STATUS_OK;
2354                 break;
2355         case PIPE_AUTH_TYPE_NTLMSSP:
2356         case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2357                 status = add_ntlmssp_auth_footer(state->cli, &hdr, ss_padding,
2358                                                  &state->outgoing_frag);
2359                 break;
2360         case PIPE_AUTH_TYPE_SCHANNEL:
2361                 status = add_schannel_auth_footer(state->cli, &hdr, ss_padding,
2362                                                   &state->outgoing_frag);
2363                 break;
2364         default:
2365                 status = NT_STATUS_INVALID_PARAMETER;
2366                 break;
2367         }
2368
2369         state->req_data_sent += data_sent_thistime;
2370         *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2371
2372         return status;
2373 }
2374
2375 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
2376 {
2377         struct tevent_req *req = tevent_req_callback_data(
2378                 subreq, struct tevent_req);
2379         struct rpc_api_pipe_req_state *state = tevent_req_data(
2380                 req, struct rpc_api_pipe_req_state);
2381         NTSTATUS status;
2382         bool is_last_frag;
2383
2384         status = rpc_write_recv(subreq);
2385         TALLOC_FREE(subreq);
2386         if (!NT_STATUS_IS_OK(status)) {
2387                 tevent_req_nterror(req, status);
2388                 return;
2389         }
2390
2391         status = prepare_next_frag(state, &is_last_frag);
2392         if (!NT_STATUS_IS_OK(status)) {
2393                 tevent_req_nterror(req, status);
2394                 return;
2395         }
2396
2397         if (is_last_frag) {
2398                 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2399                                            &state->outgoing_frag,
2400                                            DCERPC_PKT_RESPONSE);
2401                 if (tevent_req_nomem(subreq, req)) {
2402                         return;
2403                 }
2404                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2405         } else {
2406                 subreq = rpc_write_send(
2407                         state, state->ev,
2408                         state->cli->transport,
2409                         (uint8_t *)prs_data_p(&state->outgoing_frag),
2410                         prs_offset(&state->outgoing_frag));
2411                 if (tevent_req_nomem(subreq, req)) {
2412                         return;
2413                 }
2414                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2415                                         req);
2416         }
2417 }
2418
2419 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
2420 {
2421         struct tevent_req *req = tevent_req_callback_data(
2422                 subreq, struct tevent_req);
2423         struct rpc_api_pipe_req_state *state = tevent_req_data(
2424                 req, struct rpc_api_pipe_req_state);
2425         NTSTATUS status;
2426
2427         status = rpc_api_pipe_recv(subreq, state, &state->reply_pdu);
2428         TALLOC_FREE(subreq);
2429         if (!NT_STATUS_IS_OK(status)) {
2430                 tevent_req_nterror(req, status);
2431                 return;
2432         }
2433         tevent_req_done(req);
2434 }
2435
2436 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2437                                prs_struct *reply_pdu)
2438 {
2439         struct rpc_api_pipe_req_state *state = tevent_req_data(
2440                 req, struct rpc_api_pipe_req_state);
2441         NTSTATUS status;
2442
2443         if (tevent_req_is_nterror(req, &status)) {
2444                 /*
2445                  * We always have to initialize to reply pdu, even if there is
2446                  * none. The rpccli_* caller routines expect this.
2447                  */
2448                 prs_init_empty(reply_pdu, mem_ctx, UNMARSHALL);
2449                 return status;
2450         }
2451
2452         *reply_pdu = state->reply_pdu;
2453         reply_pdu->mem_ctx = mem_ctx;
2454
2455         /*
2456          * Prevent state->req_pdu from being freed
2457          * when state is freed.
2458          */
2459         talloc_steal(mem_ctx, prs_data_p(reply_pdu));
2460         prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2461
2462         return NT_STATUS_OK;
2463 }
2464
2465 #if 0
2466 /****************************************************************************
2467  Set the handle state.
2468 ****************************************************************************/
2469
2470 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
2471                                    const char *pipe_name, uint16 device_state)
2472 {
2473         bool state_set = False;
2474         char param[2];
2475         uint16 setup[2]; /* only need 2 uint16 setup parameters */
2476         char *rparam = NULL;
2477         char *rdata = NULL;
2478         uint32 rparam_len, rdata_len;
2479
2480         if (pipe_name == NULL)
2481                 return False;
2482
2483         DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
2484                  cli->fnum, pipe_name, device_state));
2485
2486         /* create parameters: device state */
2487         SSVAL(param, 0, device_state);
2488
2489         /* create setup parameters. */
2490         setup[0] = 0x0001; 
2491         setup[1] = cli->fnum; /* pipe file handle.  got this from an SMBOpenX. */
2492
2493         /* send the data on \PIPE\ */
2494         if (cli_api_pipe(cli->cli, "\\PIPE\\",
2495                     setup, 2, 0,                /* setup, length, max */
2496                     param, 2, 0,                /* param, length, max */
2497                     NULL, 0, 1024,              /* data, length, max */
2498                     &rparam, &rparam_len,        /* return param, length */
2499                     &rdata, &rdata_len))         /* return data, length */
2500         {
2501                 DEBUG(5, ("Set Handle state: return OK\n"));
2502                 state_set = True;
2503         }
2504
2505         SAFE_FREE(rparam);
2506         SAFE_FREE(rdata);
2507
2508         return state_set;
2509 }
2510 #endif
2511
2512 /****************************************************************************
2513  Check the rpc bind acknowledge response.
2514 ****************************************************************************/
2515
2516 static bool check_bind_response(RPC_HDR_BA *hdr_ba,
2517                                 const struct ndr_syntax_id *transfer)
2518 {
2519         if ( hdr_ba->addr.len == 0) {
2520                 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
2521         }
2522
2523         /* check the transfer syntax */
2524         if ((hdr_ba->transfer.if_version != transfer->if_version) ||
2525              (memcmp(&hdr_ba->transfer.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
2526                 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
2527                 return False;
2528         }
2529
2530         if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {
2531                 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
2532                           hdr_ba->res.num_results, hdr_ba->res.reason));
2533         }
2534
2535         DEBUG(5,("check_bind_response: accepted!\n"));
2536         return True;
2537 }
2538
2539 /*******************************************************************
2540  Creates a DCE/RPC bind authentication response.
2541  This is the packet that is sent back to the server once we
2542  have received a BIND-ACK, to finish the third leg of
2543  the authentication handshake.
2544  ********************************************************************/
2545
2546 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
2547                                 uint32 rpc_call_id,
2548                                 enum pipe_auth_type auth_type,
2549                                 enum dcerpc_AuthLevel auth_level,
2550                                 DATA_BLOB *pauth_blob,
2551                                 prs_struct *rpc_out)
2552 {
2553         RPC_HDR hdr;
2554         RPC_HDR_AUTH hdr_auth;
2555         uint32 pad = 0;
2556
2557         /* Create the request RPC_HDR */
2558         init_rpc_hdr(&hdr, DCERPC_PKT_AUTH3, DCERPC_PFC_FLAG_FIRST|DCERPC_PFC_FLAG_LAST, rpc_call_id,
2559                      RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,
2560                      pauth_blob->length );
2561
2562         /* Marshall it. */
2563         if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
2564                 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
2565                 return NT_STATUS_NO_MEMORY;
2566         }
2567
2568         /*
2569                 I'm puzzled about this - seems to violate the DCE RPC auth rules,
2570                 about padding - shouldn't this pad to length CLIENT_NDR_PADDING_SIZE ? JRA.
2571         */
2572
2573         /* 4 bytes padding. */
2574         if (!prs_uint32("pad", rpc_out, 0, &pad)) {
2575                 DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
2576                 return NT_STATUS_NO_MEMORY;
2577         }
2578
2579         /* Create the request RPC_HDR_AUTHA */
2580         init_rpc_hdr_auth(&hdr_auth,
2581                         map_pipe_auth_type_to_rpc_auth_type(auth_type),
2582                         auth_level, 0, 1);
2583
2584         if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {
2585                 DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
2586                 return NT_STATUS_NO_MEMORY;
2587         }
2588
2589         /*
2590          * Append the auth data to the outgoing buffer.
2591          */
2592
2593         if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {
2594                 DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
2595                 return NT_STATUS_NO_MEMORY;
2596         }
2597
2598         return NT_STATUS_OK;
2599 }
2600
2601 /*******************************************************************
2602  Creates a DCE/RPC bind alter context authentication request which
2603  may contain a spnego auth blobl
2604  ********************************************************************/
2605
2606 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
2607                                         const struct ndr_syntax_id *abstract,
2608                                         const struct ndr_syntax_id *transfer,
2609                                         enum dcerpc_AuthLevel auth_level,
2610                                         const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2611                                         prs_struct *rpc_out)
2612 {
2613         RPC_HDR_AUTH hdr_auth;
2614         prs_struct auth_info;
2615         NTSTATUS ret = NT_STATUS_OK;
2616
2617         ZERO_STRUCT(hdr_auth);
2618         if (!prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL))
2619                 return NT_STATUS_NO_MEMORY;
2620
2621         /* We may change the pad length before marshalling. */
2622         init_rpc_hdr_auth(&hdr_auth, DCERPC_AUTH_TYPE_SPNEGO, (int)auth_level, 0, 1);
2623
2624         if (pauth_blob->length) {
2625                 if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {
2626                         prs_mem_free(&auth_info);
2627                         return NT_STATUS_NO_MEMORY;
2628                 }
2629         }
2630
2631         ret = create_bind_or_alt_ctx_internal(DCERPC_PKT_ALTER,
2632                                                 rpc_out, 
2633                                                 rpc_call_id,
2634                                                 abstract,
2635                                                 transfer,
2636                                                 &hdr_auth,
2637                                                 &auth_info);
2638         prs_mem_free(&auth_info);
2639         return ret;
2640 }
2641
2642 /****************************************************************************
2643  Do an rpc bind.
2644 ****************************************************************************/
2645
2646 struct rpc_pipe_bind_state {
2647         struct event_context *ev;
2648         struct rpc_pipe_client *cli;
2649         prs_struct rpc_out;
2650         uint32_t rpc_call_id;
2651 };
2652
2653 static int rpc_pipe_bind_state_destructor(struct rpc_pipe_bind_state *state)
2654 {
2655         prs_mem_free(&state->rpc_out);
2656         return 0;
2657 }
2658
2659 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2660 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2661                                            struct rpc_pipe_bind_state *state,
2662                                            struct rpc_hdr_info *phdr,
2663                                            prs_struct *reply_pdu);
2664 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
2665 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2666                                                     struct rpc_pipe_bind_state *state,
2667                                                     struct rpc_hdr_info *phdr,
2668                                                     prs_struct *reply_pdu);
2669 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
2670
2671 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
2672                                       struct event_context *ev,
2673                                       struct rpc_pipe_client *cli,
2674                                       struct cli_pipe_auth_data *auth)
2675 {
2676         struct tevent_req *req, *subreq;
2677         struct rpc_pipe_bind_state *state;
2678         NTSTATUS status;
2679
2680         req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
2681         if (req == NULL) {
2682                 return NULL;
2683         }
2684
2685         DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2686                 rpccli_pipe_txt(talloc_tos(), cli),
2687                 (unsigned int)auth->auth_type,
2688                 (unsigned int)auth->auth_level ));
2689
2690         state->ev = ev;
2691         state->cli = cli;
2692         state->rpc_call_id = get_rpc_call_id();
2693
2694         prs_init_empty(&state->rpc_out, state, MARSHALL);
2695         talloc_set_destructor(state, rpc_pipe_bind_state_destructor);
2696
2697         cli->auth = talloc_move(cli, &auth);
2698
2699         /* Marshall the outgoing data. */
2700         status = create_rpc_bind_req(cli, &state->rpc_out,
2701                                      state->rpc_call_id,
2702                                      &cli->abstract_syntax,
2703                                      &cli->transfer_syntax,
2704                                      cli->auth->auth_type,
2705                                      cli->auth->auth_level);
2706
2707         if (!NT_STATUS_IS_OK(status)) {
2708                 goto post_status;
2709         }
2710
2711         subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
2712                                    DCERPC_PKT_BIND_ACK);
2713         if (subreq == NULL) {
2714                 goto fail;
2715         }
2716         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2717         return req;
2718
2719  post_status:
2720         tevent_req_nterror(req, status);
2721         return tevent_req_post(req, ev);
2722  fail:
2723         TALLOC_FREE(req);
2724         return NULL;
2725 }
2726
2727 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
2728 {
2729         struct tevent_req *req = tevent_req_callback_data(
2730                 subreq, struct tevent_req);
2731         struct rpc_pipe_bind_state *state = tevent_req_data(
2732                 req, struct rpc_pipe_bind_state);
2733         prs_struct reply_pdu;
2734         struct rpc_hdr_info hdr;
2735         struct rpc_hdr_ba_info hdr_ba;
2736         NTSTATUS status;
2737
2738         status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu);
2739         TALLOC_FREE(subreq);
2740         if (!NT_STATUS_IS_OK(status)) {
2741                 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2742                           rpccli_pipe_txt(talloc_tos(), state->cli),
2743                           nt_errstr(status)));
2744                 tevent_req_nterror(req, status);
2745                 return;
2746         }
2747
2748         /* Unmarshall the RPC header */
2749         if (!smb_io_rpc_hdr("hdr", &hdr, &reply_pdu, 0)) {
2750                 DEBUG(0, ("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
2751                 prs_mem_free(&reply_pdu);
2752                 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2753                 return;
2754         }
2755
2756         if (!smb_io_rpc_hdr_ba("", &hdr_ba, &reply_pdu, 0)) {
2757                 DEBUG(0, ("rpc_pipe_bind: Failed to unmarshall "
2758                           "RPC_HDR_BA.\n"));
2759                 prs_mem_free(&reply_pdu);
2760                 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2761                 return;
2762         }
2763
2764         if (!check_bind_response(&hdr_ba, &state->cli->transfer_syntax)) {
2765                 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2766                 prs_mem_free(&reply_pdu);
2767                 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2768                 return;
2769         }
2770
2771         state->cli->max_xmit_frag = hdr_ba.bba.max_tsize;
2772         state->cli->max_recv_frag = hdr_ba.bba.max_rsize;
2773
2774         /*
2775          * For authenticated binds we may need to do 3 or 4 leg binds.
2776          */
2777
2778         switch(state->cli->auth->auth_type) {
2779
2780         case PIPE_AUTH_TYPE_NONE:
2781         case PIPE_AUTH_TYPE_SCHANNEL:
2782                 /* Bind complete. */
2783                 prs_mem_free(&reply_pdu);
2784                 tevent_req_done(req);
2785                 break;
2786
2787         case PIPE_AUTH_TYPE_NTLMSSP:
2788                 /* Need to send AUTH3 packet - no reply. */
2789                 status = rpc_finish_auth3_bind_send(req, state, &hdr,
2790                                                     &reply_pdu);
2791                 prs_mem_free(&reply_pdu);
2792                 if (!NT_STATUS_IS_OK(status)) {
2793                         tevent_req_nterror(req, status);
2794                 }
2795                 break;
2796
2797         case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2798                 /* Need to send alter context request and reply. */
2799                 status = rpc_finish_spnego_ntlmssp_bind_send(req, state, &hdr,
2800                                                              &reply_pdu);
2801                 prs_mem_free(&reply_pdu);
2802                 if (!NT_STATUS_IS_OK(status)) {
2803                         tevent_req_nterror(req, status);
2804                 }
2805                 break;
2806
2807         case PIPE_AUTH_TYPE_KRB5:
2808                 /* */
2809
2810         default:
2811                 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2812                          (unsigned int)state->cli->auth->auth_type));
2813                 prs_mem_free(&reply_pdu);
2814                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2815         }
2816 }
2817
2818 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2819                                            struct rpc_pipe_bind_state *state,
2820                                            struct rpc_hdr_info *phdr,
2821                                            prs_struct *reply_pdu)
2822 {
2823         DATA_BLOB server_response = data_blob_null;
2824         DATA_BLOB client_reply = data_blob_null;
2825         struct rpc_hdr_auth_info hdr_auth;
2826         struct tevent_req *subreq;
2827         NTSTATUS status;
2828
2829         if ((phdr->auth_len == 0)
2830             || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
2831                 return NT_STATUS_INVALID_PARAMETER;
2832         }
2833
2834         if (!prs_set_offset(
2835                     reply_pdu,
2836                     phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2837                 return NT_STATUS_INVALID_PARAMETER;
2838         }
2839
2840         if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, reply_pdu, 0)) {
2841                 return NT_STATUS_INVALID_PARAMETER;
2842         }
2843
2844         /* TODO - check auth_type/auth_level match. */
2845
2846         server_response = data_blob_talloc(talloc_tos(), NULL, phdr->auth_len);
2847         prs_copy_data_out((char *)server_response.data, reply_pdu,
2848                           phdr->auth_len);
2849
2850         status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2851                                 server_response, &client_reply);
2852
2853         if (!NT_STATUS_IS_OK(status)) {
2854                 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
2855                           "blob failed: %s.\n", nt_errstr(status)));
2856                 return status;
2857         }
2858
2859         prs_init_empty(&state->rpc_out, talloc_tos(), MARSHALL);
2860
2861         status = create_rpc_bind_auth3(state->cli, state->rpc_call_id,
2862                                        state->cli->auth->auth_type,
2863                                        state->cli->auth->auth_level,
2864                                        &client_reply, &state->rpc_out);
2865         data_blob_free(&client_reply);
2866
2867         if (!NT_STATUS_IS_OK(status)) {
2868                 return status;
2869         }
2870
2871         subreq = rpc_write_send(state, state->ev, state->cli->transport,
2872                                 (uint8_t *)prs_data_p(&state->rpc_out),
2873                                 prs_offset(&state->rpc_out));
2874         if (subreq == NULL) {
2875                 return NT_STATUS_NO_MEMORY;
2876         }
2877         tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
2878         return NT_STATUS_OK;
2879 }
2880
2881 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
2882 {
2883         struct tevent_req *req = tevent_req_callback_data(
2884                 subreq, struct tevent_req);
2885         NTSTATUS status;
2886
2887         status = rpc_write_recv(subreq);
2888         TALLOC_FREE(subreq);
2889         if (!NT_STATUS_IS_OK(status)) {
2890                 tevent_req_nterror(req, status);
2891                 return;
2892         }
2893         tevent_req_done(req);
2894 }
2895
2896 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2897                                                     struct rpc_pipe_bind_state *state,
2898                                                     struct rpc_hdr_info *phdr,
2899                                                     prs_struct *reply_pdu)
2900 {
2901         DATA_BLOB server_spnego_response = data_blob_null;
2902         DATA_BLOB server_ntlm_response = data_blob_null;
2903         DATA_BLOB client_reply = data_blob_null;
2904         DATA_BLOB tmp_blob = data_blob_null;
2905         RPC_HDR_AUTH hdr_auth;
2906         struct tevent_req *subreq;
2907         NTSTATUS status;
2908
2909         if ((phdr->auth_len == 0)
2910             || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
2911                 return NT_STATUS_INVALID_PARAMETER;
2912         }
2913
2914         /* Process the returned NTLMSSP blob first. */
2915         if (!prs_set_offset(
2916                     reply_pdu,
2917                     phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
2918                 return NT_STATUS_INVALID_PARAMETER;
2919         }
2920
2921         if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, reply_pdu, 0)) {
2922                 return NT_STATUS_INVALID_PARAMETER;
2923         }
2924
2925         server_spnego_response = data_blob(NULL, phdr->auth_len);
2926         prs_copy_data_out((char *)server_spnego_response.data,
2927                           reply_pdu, phdr->auth_len);
2928
2929         /*
2930          * The server might give us back two challenges - tmp_blob is for the
2931          * second.
2932          */
2933         if (!spnego_parse_challenge(server_spnego_response,
2934                                     &server_ntlm_response, &tmp_blob)) {
2935                 data_blob_free(&server_spnego_response);
2936                 data_blob_free(&server_ntlm_response);
2937                 data_blob_free(&tmp_blob);
2938                 return NT_STATUS_INVALID_PARAMETER;
2939         }
2940
2941         /* We're finished with the server spnego response and the tmp_blob. */
2942         data_blob_free(&server_spnego_response);
2943         data_blob_free(&tmp_blob);
2944
2945         status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2946                                 server_ntlm_response, &client_reply);
2947
2948         /* Finished with the server_ntlm response */
2949         data_blob_free(&server_ntlm_response);
2950
2951         if (!NT_STATUS_IS_OK(status)) {
2952                 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
2953                           "using server blob failed.\n"));
2954                 data_blob_free(&client_reply);
2955                 return status;
2956         }
2957
2958         /* SPNEGO wrap the client reply. */
2959         tmp_blob = spnego_gen_auth(client_reply);
2960         data_blob_free(&client_reply);
2961         client_reply = tmp_blob;
2962         tmp_blob = data_blob_null;
2963
2964         /* Now prepare the alter context pdu. */
2965         prs_init_empty(&state->rpc_out, state, MARSHALL);
2966
2967         status = create_rpc_alter_context(state->rpc_call_id,
2968                                           &state->cli->abstract_syntax,
2969                                           &state->cli->transfer_syntax,
2970                                           state->cli->auth->auth_level,
2971                                           &client_reply,
2972                                           &state->rpc_out);
2973         data_blob_free(&client_reply);
2974
2975         if (!NT_STATUS_IS_OK(status)) {
2976                 return status;
2977         }
2978
2979         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2980                                    &state->rpc_out, DCERPC_PKT_ALTER_RESP);
2981         if (subreq == NULL) {
2982                 return NT_STATUS_NO_MEMORY;
2983         }
2984         tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req);
2985         return NT_STATUS_OK;
2986 }
2987
2988 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
2989 {
2990         struct tevent_req *req = tevent_req_callback_data(
2991                 subreq, struct tevent_req);
2992         struct rpc_pipe_bind_state *state = tevent_req_data(
2993                 req, struct rpc_pipe_bind_state);
2994         DATA_BLOB server_spnego_response = data_blob_null;
2995         DATA_BLOB tmp_blob = data_blob_null;
2996         prs_struct reply_pdu;
2997         struct rpc_hdr_info hdr;
2998         struct rpc_hdr_auth_info hdr_auth;
2999         NTSTATUS status;
3000
3001         status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu);
3002         TALLOC_FREE(subreq);
3003         if (!NT_STATUS_IS_OK(status)) {
3004                 tevent_req_nterror(req, status);
3005                 return;
3006         }
3007
3008         /* Get the auth blob from the reply. */
3009         if (!smb_io_rpc_hdr("rpc_hdr   ", &hdr, &reply_pdu, 0)) {
3010                 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: Failed to "
3011                           "unmarshall RPC_HDR.\n"));
3012                 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3013                 return;
3014         }
3015
3016         if (!prs_set_offset(
3017                     &reply_pdu,
3018                     hdr.frag_len - hdr.auth_len - RPC_HDR_AUTH_LEN)) {
3019                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
3020                 return;
3021         }
3022
3023         if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &reply_pdu, 0)) {
3024                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
3025                 return;
3026         }
3027
3028         server_spnego_response = data_blob(NULL, hdr.auth_len);
3029         prs_copy_data_out((char *)server_spnego_response.data, &reply_pdu,
3030                           hdr.auth_len);
3031
3032         /* Check we got a valid auth response. */
3033         if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK,
3034                                         OID_NTLMSSP, &tmp_blob)) {
3035                 data_blob_free(&server_spnego_response);
3036                 data_blob_free(&tmp_blob);
3037                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
3038                 return;
3039         }
3040
3041         data_blob_free(&server_spnego_response);
3042         data_blob_free(&tmp_blob);
3043
3044         DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
3045                  "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
3046         tevent_req_done(req);
3047 }
3048
3049 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
3050 {
3051         return tevent_req_simple_recv_ntstatus(req);
3052 }
3053
3054 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
3055                        struct cli_pipe_auth_data *auth)
3056 {
3057         TALLOC_CTX *frame = talloc_stackframe();
3058         struct event_context *ev;
3059         struct tevent_req *req;
3060         NTSTATUS status = NT_STATUS_OK;
3061
3062         ev = event_context_init(frame);
3063         if (ev == NULL) {
3064                 status = NT_STATUS_NO_MEMORY;
3065                 goto fail;
3066         }
3067
3068         req = rpc_pipe_bind_send(frame, ev, cli, auth);
3069         if (req == NULL) {
3070                 status = NT_STATUS_NO_MEMORY;
3071                 goto fail;
3072         }
3073
3074         if (!tevent_req_poll(req, ev)) {
3075                 status = map_nt_error_from_unix(errno);
3076                 goto fail;
3077         }
3078
3079         status = rpc_pipe_bind_recv(req);
3080  fail:
3081         TALLOC_FREE(frame);
3082         return status;
3083 }
3084
3085 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
3086
3087 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
3088                                 unsigned int timeout)
3089 {
3090         unsigned int old;
3091
3092         if (rpc_cli->transport == NULL) {
3093                 return RPCCLI_DEFAULT_TIMEOUT;
3094         }
3095
3096         if (rpc_cli->transport->set_timeout == NULL) {
3097                 return RPCCLI_DEFAULT_TIMEOUT;
3098         }
3099
3100         old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
3101         if (old == 0) {
3102                 return RPCCLI_DEFAULT_TIMEOUT;
3103         }
3104
3105         return old;
3106 }
3107
3108 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
3109 {
3110         if (rpc_cli == NULL) {
3111                 return false;
3112         }
3113
3114         if (rpc_cli->transport == NULL) {
3115                 return false;
3116         }
3117
3118         return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
3119 }
3120
3121 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
3122 {
3123         struct cli_state *cli;
3124
3125         if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
3126             || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
3127                 memcpy(nt_hash, rpc_cli->auth->a_u.ntlmssp_state->nt_hash, 16);
3128                 return true;
3129         }
3130
3131         cli = rpc_pipe_np_smb_conn(rpc_cli);
3132         if (cli == NULL) {
3133                 return false;
3134         }
3135         E_md4hash(cli->password ? cli->password : "", nt_hash);
3136         return true;
3137 }
3138
3139 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
3140                                struct cli_pipe_auth_data **presult)
3141 {
3142         struct cli_pipe_auth_data *result;
3143
3144         result = talloc(mem_ctx, struct cli_pipe_auth_data);
3145         if (result == NULL) {
3146                 return NT_STATUS_NO_MEMORY;
3147         }
3148
3149         result->auth_type = PIPE_AUTH_TYPE_NONE;
3150         result->auth_level = DCERPC_AUTH_LEVEL_NONE;
3151
3152         result->user_name = talloc_strdup(result, "");
3153         result->domain = talloc_strdup(result, "");
3154         if ((result->user_name == NULL) || (result->domain == NULL)) {
3155                 TALLOC_FREE(result);
3156                 return NT_STATUS_NO_MEMORY;
3157         }
3158
3159         *presult = result;
3160         return NT_STATUS_OK;
3161 }
3162
3163 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
3164 {
3165         ntlmssp_end(&auth->a_u.ntlmssp_state);
3166         return 0;
3167 }
3168
3169 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
3170                                   enum pipe_auth_type auth_type,
3171                                   enum dcerpc_AuthLevel auth_level,
3172                                   const char *domain,
3173                                   const char *username,
3174                                   const char *password,
3175                                   struct cli_pipe_auth_data **presult)
3176 {
3177         struct cli_pipe_auth_data *result;
3178         NTSTATUS status;
3179
3180         result = talloc(mem_ctx, struct cli_pipe_auth_data);
3181         if (result == NULL) {
3182                 return NT_STATUS_NO_MEMORY;
3183         }
3184
3185         result->auth_type = auth_type;
3186         result->auth_level = auth_level;
3187
3188         result->user_name = talloc_strdup(result, username);
3189         result->domain = talloc_strdup(result, domain);
3190         if ((result->user_name == NULL) || (result->domain == NULL)) {
3191                 status = NT_STATUS_NO_MEMORY;
3192                 goto fail;
3193         }
3194
3195         status = ntlmssp_client_start(NULL,
3196                                       global_myname(),
3197                                       lp_workgroup(),
3198                                       lp_client_ntlmv2_auth(),
3199                                       &result->a_u.ntlmssp_state);
3200         if (!NT_STATUS_IS_OK(status)) {
3201                 goto fail;
3202         }
3203
3204         talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
3205
3206         status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
3207         if (!NT_STATUS_IS_OK(status)) {
3208                 goto fail;
3209         }
3210
3211         status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
3212         if (!NT_STATUS_IS_OK(status)) {
3213                 goto fail;
3214         }
3215
3216         status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
3217         if (!NT_STATUS_IS_OK(status)) {
3218                 goto fail;
3219         }
3220
3221         /*
3222          * Turn off sign+seal to allow selected auth level to turn it back on.
3223          */
3224         result->a_u.ntlmssp_state->neg_flags &=
3225                 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
3226
3227         if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
3228                 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
3229         } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
3230                 result->a_u.ntlmssp_state->neg_flags
3231                         |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
3232         }
3233
3234         *presult = result;
3235         return NT_STATUS_OK;
3236
3237  fail:
3238         TALLOC_FREE(result);
3239         return status;
3240 }
3241
3242 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
3243                                    enum dcerpc_AuthLevel auth_level,
3244                                    struct netlogon_creds_CredentialState *creds,
3245                                    struct cli_pipe_auth_data **presult)
3246 {
3247         struct cli_pipe_auth_data *result;
3248
3249         result = talloc(mem_ctx, struct cli_pipe_auth_data);
3250         if (result == NULL) {
3251                 return NT_STATUS_NO_MEMORY;
3252         }
3253
3254         result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
3255         result->auth_level = auth_level;
3256
3257         result->user_name = talloc_strdup(result, "");
3258         result->domain = talloc_strdup(result, domain);
3259         if ((result->user_name == NULL) || (result->domain == NULL)) {
3260                 goto fail;
3261         }
3262
3263         result->a_u.schannel_auth = talloc(result, struct schannel_state);
3264         if (result->a_u.schannel_auth == NULL) {
3265                 goto fail;
3266         }
3267
3268         result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
3269         result->a_u.schannel_auth->seq_num = 0;
3270         result->a_u.schannel_auth->initiator = true;
3271         result->a_u.schannel_auth->creds = creds;
3272
3273         *presult = result;
3274         return NT_STATUS_OK;
3275
3276  fail:
3277         TALLOC_FREE(result);
3278         return NT_STATUS_NO_MEMORY;
3279 }
3280
3281 #ifdef HAVE_KRB5
3282 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
3283 {
3284         data_blob_free(&auth->session_key);
3285         return 0;
3286 }
3287 #endif
3288
3289 static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
3290                                    enum dcerpc_AuthLevel auth_level,
3291                                    const char *service_princ,
3292                                    const char *username,
3293                                    const char *password,
3294                                    struct cli_pipe_auth_data **presult)
3295 {
3296 #ifdef HAVE_KRB5
3297         struct cli_pipe_auth_data *result;
3298
3299         if ((username != NULL) && (password != NULL)) {
3300                 int ret = kerberos_kinit_password(username, password, 0, NULL);
3301                 if (ret != 0) {
3302                         return NT_STATUS_ACCESS_DENIED;
3303                 }
3304         }
3305
3306         result = talloc(mem_ctx, struct cli_pipe_auth_data);
3307         if (result == NULL) {
3308                 return NT_STATUS_NO_MEMORY;
3309         }
3310
3311         result->auth_type = PIPE_AUTH_TYPE_KRB5;
3312         result->auth_level = auth_level;
3313
3314         /*
3315          * Username / domain need fixing!
3316          */
3317         result->user_name = talloc_strdup(result, "");
3318         result->domain = talloc_strdup(result, "");
3319         if ((result->user_name == NULL) || (result->domain == NULL)) {
3320                 goto fail;
3321         }
3322
3323         result->a_u.kerberos_auth = TALLOC_ZERO_P(
3324                 result, struct kerberos_auth_struct);
3325         if (result->a_u.kerberos_auth == NULL) {
3326                 goto fail;
3327         }
3328         talloc_set_destructor(result->a_u.kerberos_auth,
3329                               cli_auth_kerberos_data_destructor);
3330
3331         result->a_u.kerberos_auth->service_principal = talloc_strdup(
3332                 result, service_princ);
3333         if (result->a_u.kerberos_auth->service_principal == NULL) {
3334                 goto fail;
3335         }
3336
3337         *presult = result;
3338         return NT_STATUS_OK;
3339
3340  fail:
3341         TALLOC_FREE(result);
3342         return NT_STATUS_NO_MEMORY;
3343 #else
3344         return NT_STATUS_NOT_SUPPORTED;
3345 #endif
3346 }
3347
3348 /**
3349  * Create an rpc pipe client struct, connecting to a tcp port.
3350  */
3351 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
3352                                        uint16_t port,
3353                                        const struct ndr_syntax_id *abstract_syntax,
3354                                        struct rpc_pipe_client **presult)
3355 {
3356         struct rpc_pipe_client *result;
3357         struct sockaddr_storage addr;
3358         NTSTATUS status;
3359         int fd;
3360
3361         result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
3362         if (result == NULL) {
3363                 return NT_STATUS_NO_MEMORY;
3364         }
3365
3366         result->abstract_syntax = *abstract_syntax;
3367         result->transfer_syntax = ndr_transfer_syntax;
3368         result->dispatch = cli_do_rpc_ndr;
3369         result->dispatch_send = cli_do_rpc_ndr_send;
3370         result->dispatch_recv = cli_do_rpc_ndr_recv;
3371
3372         result->desthost = talloc_strdup(result, host);
3373         result->srv_name_slash = talloc_asprintf_strupper_m(
3374                 result, "\\\\%s", result->desthost);
3375         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3376                 status = NT_STATUS_NO_MEMORY;
3377                 goto fail;
3378         }
3379
3380         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3381         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3382
3383         if (!resolve_name(host, &addr, 0, false)) {
3384                 status = NT_STATUS_NOT_FOUND;
3385                 goto fail;
3386         }
3387
3388         status = open_socket_out(&addr, port, 60, &fd);
3389         if (!NT_STATUS_IS_OK(status)) {
3390                 goto fail;
3391         }
3392         set_socket_options(fd, lp_socket_options());
3393
3394         status = rpc_transport_sock_init(result, fd, &result->transport);
3395         if (!NT_STATUS_IS_OK(status)) {
3396                 close(fd);
3397                 goto fail;
3398         }
3399
3400         result->transport->transport = NCACN_IP_TCP;
3401
3402         *presult = result;
3403         return NT_STATUS_OK;
3404
3405  fail:
3406         TALLOC_FREE(result);
3407         return status;
3408 }
3409
3410 /**
3411  * Determine the tcp port on which a dcerpc interface is listening
3412  * for the ncacn_ip_tcp transport via the endpoint mapper of the
3413  * target host.
3414  */
3415 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
3416                                       const struct ndr_syntax_id *abstract_syntax,
3417                                       uint16_t *pport)
3418 {
3419         NTSTATUS status;
3420         struct rpc_pipe_client *epm_pipe = NULL;
3421         struct cli_pipe_auth_data *auth = NULL;
3422         struct dcerpc_binding *map_binding = NULL;
3423         struct dcerpc_binding *res_binding = NULL;
3424         struct epm_twr_t *map_tower = NULL;
3425         struct epm_twr_t *res_towers = NULL;
3426         struct policy_handle *entry_handle = NULL;
3427         uint32_t num_towers = 0;
3428         uint32_t max_towers = 1;
3429         struct epm_twr_p_t towers;
3430         TALLOC_CTX *tmp_ctx = talloc_stackframe();
3431
3432         if (pport == NULL) {
3433                 status = NT_STATUS_INVALID_PARAMETER;
3434                 goto done;
3435         }
3436
3437         /* open the connection to the endpoint mapper */
3438         status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
3439                                         &ndr_table_epmapper.syntax_id,
3440                                         &epm_pipe);
3441
3442         if (!NT_STATUS_IS_OK(status)) {
3443                 goto done;
3444         }
3445
3446         status = rpccli_anon_bind_data(tmp_ctx, &auth);
3447         if (!NT_STATUS_IS_OK(status)) {
3448                 goto done;
3449         }
3450
3451         status = rpc_pipe_bind(epm_pipe, auth);
3452         if (!NT_STATUS_IS_OK(status)) {
3453                 goto done;
3454         }
3455
3456         /* create tower for asking the epmapper */
3457
3458         map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
3459         if (map_binding == NULL) {
3460                 status = NT_STATUS_NO_MEMORY;
3461                 goto done;
3462         }
3463
3464         map_binding->transport = NCACN_IP_TCP;
3465         map_binding->object = *abstract_syntax;
3466         map_binding->host = host; /* needed? */
3467         map_binding->endpoint = "0"; /* correct? needed? */
3468
3469         map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
3470         if (map_tower == NULL) {
3471                 status = NT_STATUS_NO_MEMORY;
3472                 goto done;
3473         }
3474
3475         status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
3476                                             &(map_tower->tower));
3477         if (!NT_STATUS_IS_OK(status)) {
3478                 goto done;
3479         }
3480
3481         /* allocate further parameters for the epm_Map call */
3482
3483         res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
3484         if (res_towers == NULL) {
3485                 status = NT_STATUS_NO_MEMORY;
3486                 goto done;
3487         }
3488         towers.twr = res_towers;
3489
3490         entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
3491         if (entry_handle == NULL) {
3492                 status = NT_STATUS_NO_MEMORY;
3493                 goto done;
3494         }
3495
3496         /* ask the endpoint mapper for the port */
3497
3498         status = rpccli_epm_Map(epm_pipe,
3499                                 tmp_ctx,
3500                                 CONST_DISCARD(struct GUID *,
3501                                               &(abstract_syntax->uuid)),
3502                                 map_tower,
3503                                 entry_handle,
3504                                 max_towers,
3505                                 &num_towers,
3506                                 &towers);
3507
3508         if (!NT_STATUS_IS_OK(status)) {
3509                 goto done;
3510         }
3511
3512         if (num_towers != 1) {
3513                 status = NT_STATUS_UNSUCCESSFUL;
3514                 goto done;
3515         }
3516
3517         /* extract the port from the answer */
3518
3519         status = dcerpc_binding_from_tower(tmp_ctx,
3520                                            &(towers.twr->tower),
3521                                            &res_binding);
3522         if (!NT_STATUS_IS_OK(status)) {
3523                 goto done;
3524         }
3525
3526         /* are further checks here necessary? */
3527         if (res_binding->transport != NCACN_IP_TCP) {
3528                 status = NT_STATUS_UNSUCCESSFUL;
3529                 goto done;
3530         }
3531
3532         *pport = (uint16_t)atoi(res_binding->endpoint);
3533
3534 done:
3535         TALLOC_FREE(tmp_ctx);
3536         return status;
3537 }
3538
3539 /**
3540  * Create a rpc pipe client struct, connecting to a host via tcp.
3541  * The port is determined by asking the endpoint mapper on the given
3542  * host.
3543  */
3544 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
3545                            const struct ndr_syntax_id *abstract_syntax,
3546                            struct rpc_pipe_client **presult)
3547 {
3548         NTSTATUS status;
3549         uint16_t port = 0;
3550
3551         status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
3552         if (!NT_STATUS_IS_OK(status)) {
3553                 return status;
3554         }
3555
3556         return rpc_pipe_open_tcp_port(mem_ctx, host, port,
3557                                         abstract_syntax, presult);
3558 }
3559
3560 /********************************************************************
3561  Create a rpc pipe client struct, connecting to a unix domain socket
3562  ********************************************************************/
3563 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
3564                                const struct ndr_syntax_id *abstract_syntax,
3565                                struct rpc_pipe_client **presult)
3566 {
3567         struct rpc_pipe_client *result;
3568         struct sockaddr_un addr;
3569         NTSTATUS status;
3570         int fd;
3571
3572         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3573         if (result == NULL) {
3574                 return NT_STATUS_NO_MEMORY;
3575         }
3576
3577         result->abstract_syntax = *abstract_syntax;
3578         result->transfer_syntax = ndr_transfer_syntax;
3579         result->dispatch = cli_do_rpc_ndr;
3580         result->dispatch_send = cli_do_rpc_ndr_send;
3581         result->dispatch_recv = cli_do_rpc_ndr_recv;
3582
3583         result->desthost = get_myname(result);
3584         result->srv_name_slash = talloc_asprintf_strupper_m(
3585                 result, "\\\\%s", result->desthost);
3586         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3587                 status = NT_STATUS_NO_MEMORY;
3588                 goto fail;
3589         }
3590
3591         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3592         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3593
3594         fd = socket(AF_UNIX, SOCK_STREAM, 0);
3595         if (fd == -1) {
3596                 status = map_nt_error_from_unix(errno);
3597                 goto fail;
3598         }
3599
3600         ZERO_STRUCT(addr);
3601         addr.sun_family = AF_UNIX;
3602         strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
3603
3604         if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
3605                 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
3606                           strerror(errno)));
3607                 close(fd);
3608                 return map_nt_error_from_unix(errno);
3609         }
3610
3611         status = rpc_transport_sock_init(result, fd, &result->transport);
3612         if (!NT_STATUS_IS_OK(status)) {
3613                 close(fd);
3614                 goto fail;
3615         }
3616
3617         result->transport->transport = NCALRPC;
3618
3619         *presult = result;
3620         return NT_STATUS_OK;
3621
3622  fail:
3623         TALLOC_FREE(result);
3624         return status;
3625 }
3626
3627 struct rpc_pipe_client_np_ref {
3628         struct cli_state *cli;
3629         struct rpc_pipe_client *pipe;
3630 };
3631
3632 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3633 {
3634         DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3635         return 0;
3636 }
3637
3638 /****************************************************************************
3639  Open a named pipe over SMB to a remote server.
3640  *
3641  * CAVEAT CALLER OF THIS FUNCTION:
3642  *    The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3643  *    so be sure that this function is called AFTER any structure (vs pointer)
3644  *    assignment of the cli.  In particular, libsmbclient does structure
3645  *    assignments of cli, which invalidates the data in the returned
3646  *    rpc_pipe_client if this function is called before the structure assignment
3647  *    of cli.
3648  * 
3649  ****************************************************************************/
3650
3651 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3652                                  const struct ndr_syntax_id *abstract_syntax,
3653                                  struct rpc_pipe_client **presult)
3654 {
3655         struct rpc_pipe_client *result;
3656         NTSTATUS status;
3657         struct rpc_pipe_client_np_ref *np_ref;
3658
3659         /* sanity check to protect against crashes */
3660
3661         if ( !cli ) {
3662                 return NT_STATUS_INVALID_HANDLE;
3663         }
3664
3665         result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
3666         if (result == NULL) {
3667                 return NT_STATUS_NO_MEMORY;
3668         }
3669
3670         result->abstract_syntax = *abstract_syntax;
3671         result->transfer_syntax = ndr_transfer_syntax;
3672         result->dispatch = cli_do_rpc_ndr;
3673         result->dispatch_send = cli_do_rpc_ndr_send;
3674         result->dispatch_recv = cli_do_rpc_ndr_recv;
3675         result->desthost = talloc_strdup(result, cli->desthost);
3676         result->srv_name_slash = talloc_asprintf_strupper_m(
3677                 result, "\\\\%s", result->desthost);
3678
3679         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3680         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3681
3682         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3683                 TALLOC_FREE(result);
3684                 return NT_STATUS_NO_MEMORY;
3685         }
3686
3687         status = rpc_transport_np_init(result, cli, abstract_syntax,
3688                                        &result->transport);
3689         if (!NT_STATUS_IS_OK(status)) {
3690                 TALLOC_FREE(result);
3691                 return status;
3692         }
3693
3694         result->transport->transport = NCACN_NP;
3695
3696         np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3697         if (np_ref == NULL) {
3698                 TALLOC_FREE(result);
3699                 return NT_STATUS_NO_MEMORY;
3700         }
3701         np_ref->cli = cli;
3702         np_ref->pipe = result;
3703
3704         DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3705         talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3706
3707         *presult = result;
3708         return NT_STATUS_OK;
3709 }
3710
3711 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
3712                              struct rpc_cli_smbd_conn *conn,
3713                              const struct ndr_syntax_id *syntax,
3714                              struct rpc_pipe_client **presult)
3715 {
3716         struct rpc_pipe_client *result;
3717         struct cli_pipe_auth_data *auth;
3718         NTSTATUS status;
3719
3720         result = talloc(mem_ctx, struct rpc_pipe_client);
3721         if (result == NULL) {
3722                 return NT_STATUS_NO_MEMORY;
3723         }
3724         result->abstract_syntax = *syntax;
3725         result->transfer_syntax = ndr_transfer_syntax;
3726         result->dispatch = cli_do_rpc_ndr;
3727         result->dispatch_send = cli_do_rpc_ndr_send;
3728         result->dispatch_recv = cli_do_rpc_ndr_recv;
3729         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3730         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3731
3732         result->desthost = talloc_strdup(result, global_myname());
3733         result->srv_name_slash = talloc_asprintf_strupper_m(
3734                 result, "\\\\%s", global_myname());
3735         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3736                 TALLOC_FREE(result);
3737                 return NT_STATUS_NO_MEMORY;
3738         }
3739
3740         status = rpc_transport_smbd_init(result, conn, syntax,
3741                                          &result->transport);
3742         if (!NT_STATUS_IS_OK(status)) {
3743                 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3744                           nt_errstr(status)));
3745                 TALLOC_FREE(result);
3746                 return status;
3747         }
3748
3749         status = rpccli_anon_bind_data(result, &auth);
3750         if (!NT_STATUS_IS_OK(status)) {
3751                 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3752                           nt_errstr(status)));
3753                 TALLOC_FREE(result);
3754                 return status;
3755         }
3756
3757         status = rpc_pipe_bind(result, auth);
3758         if (!NT_STATUS_IS_OK(status)) {
3759                 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
3760                 TALLOC_FREE(result);
3761                 return status;
3762         }
3763
3764         result->transport->transport = NCACN_INTERNAL;
3765
3766         *presult = result;
3767         return NT_STATUS_OK;
3768 }
3769
3770 /****************************************************************************
3771  Open a pipe to a remote server.
3772  ****************************************************************************/
3773
3774 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3775                                   enum dcerpc_transport_t transport,
3776                                   const struct ndr_syntax_id *interface,
3777                                   struct rpc_pipe_client **presult)
3778 {
3779         switch (transport) {
3780         case NCACN_IP_TCP:
3781                 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
3782                                          presult);
3783         case NCACN_NP:
3784                 return rpc_pipe_open_np(cli, interface, presult);
3785         default:
3786                 return NT_STATUS_NOT_IMPLEMENTED;
3787         }
3788 }
3789
3790 /****************************************************************************
3791  Open a named pipe to an SMB server and bind anonymously.
3792  ****************************************************************************/
3793
3794 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3795                                             enum dcerpc_transport_t transport,
3796                                             const struct ndr_syntax_id *interface,
3797                                             struct rpc_pipe_client **presult)
3798 {
3799         struct rpc_pipe_client *result;
3800         struct cli_pipe_auth_data *auth;
3801         NTSTATUS status;
3802
3803         status = cli_rpc_pipe_open(cli, transport, interface, &result);
3804         if (!NT_STATUS_IS_OK(status)) {
3805                 return status;
3806         }
3807
3808         status = rpccli_anon_bind_data(result, &auth);
3809         if (!NT_STATUS_IS_OK(status)) {
3810                 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3811                           nt_errstr(status)));
3812                 TALLOC_FREE(result);
3813                 return status;
3814         }
3815
3816         /*
3817          * This is a bit of an abstraction violation due to the fact that an
3818          * anonymous bind on an authenticated SMB inherits the user/domain
3819          * from the enclosing SMB creds
3820          */
3821
3822         TALLOC_FREE(auth->user_name);
3823         TALLOC_FREE(auth->domain);
3824
3825         auth->user_name = talloc_strdup(auth, cli->user_name);
3826         auth->domain = talloc_strdup(auth, cli->domain);
3827         auth->user_session_key = data_blob_talloc(auth,
3828                 cli->user_session_key.data,
3829                 cli->user_session_key.length);
3830
3831         if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3832                 TALLOC_FREE(result);
3833                 return NT_STATUS_NO_MEMORY;
3834         }
3835
3836         status = rpc_pipe_bind(result, auth);
3837         if (!NT_STATUS_IS_OK(status)) {
3838                 int lvl = 0;
3839                 if (ndr_syntax_id_equal(interface,
3840                                         &ndr_table_dssetup.syntax_id)) {
3841                         /* non AD domains just don't have this pipe, avoid
3842                          * level 0 statement in that case - gd */
3843                         lvl = 3;
3844                 }
3845                 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3846                             "%s failed with error %s\n",
3847                             get_pipe_name_from_syntax(talloc_tos(), interface),
3848                             nt_errstr(status) ));
3849                 TALLOC_FREE(result);
3850                 return status;
3851         }
3852
3853         DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3854                   "%s and bound anonymously.\n",
3855                   get_pipe_name_from_syntax(talloc_tos(), interface),
3856                   cli->desthost));
3857
3858         *presult = result;
3859         return NT_STATUS_OK;
3860 }
3861
3862 /****************************************************************************
3863  ****************************************************************************/
3864
3865 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3866                                   const struct ndr_syntax_id *interface,
3867                                   struct rpc_pipe_client **presult)
3868 {
3869         return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3870                                                   interface, presult);
3871 }
3872
3873 /****************************************************************************
3874  Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
3875  ****************************************************************************/
3876
3877 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
3878                                                    const struct ndr_syntax_id *interface,
3879                                                    enum dcerpc_transport_t transport,
3880                                                    enum pipe_auth_type auth_type,
3881                                                    enum dcerpc_AuthLevel auth_level,
3882                                                    const char *domain,
3883                                                    const char *username,
3884                                                    const char *password,
3885                                                    struct rpc_pipe_client **presult)
3886 {
3887         struct rpc_pipe_client *result;
3888         struct cli_pipe_auth_data *auth;
3889         NTSTATUS status;
3890
3891         status = cli_rpc_pipe_open(cli, transport, interface, &result);
3892         if (!NT_STATUS_IS_OK(status)) {
3893                 return status;
3894         }
3895
3896         status = rpccli_ntlmssp_bind_data(
3897                 result, auth_type, auth_level, domain, username,
3898                 password, &auth);
3899         if (!NT_STATUS_IS_OK(status)) {
3900                 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
3901                           nt_errstr(status)));
3902                 goto err;
3903         }
3904
3905         status = rpc_pipe_bind(result, auth);
3906         if (!NT_STATUS_IS_OK(status)) {
3907                 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
3908                         nt_errstr(status) ));
3909                 goto err;
3910         }
3911
3912         DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
3913                 "machine %s and bound NTLMSSP as user %s\\%s.\n",
3914                   get_pipe_name_from_syntax(talloc_tos(), interface),
3915                   cli->desthost, domain, username ));
3916
3917         *presult = result;
3918         return NT_STATUS_OK;
3919
3920   err:
3921
3922         TALLOC_FREE(result);
3923         return status;
3924 }
3925
3926 /****************************************************************************
3927  External interface.
3928  Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
3929  ****************************************************************************/
3930
3931 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
3932                                    const struct ndr_syntax_id *interface,
3933                                    enum dcerpc_transport_t transport,
3934                                    enum dcerpc_AuthLevel auth_level,
3935                                    const char *domain,
3936                                    const char *username,
3937                                    const char *password,
3938                                    struct rpc_pipe_client **presult)
3939 {
3940         return cli_rpc_pipe_open_ntlmssp_internal(cli,
3941                                                 interface,
3942                                                 transport,
3943                                                 PIPE_AUTH_TYPE_NTLMSSP,
3944                                                 auth_level,
3945                                                 domain,
3946                                                 username,
3947                                                 password,
3948                                                 presult);
3949 }
3950
3951 /****************************************************************************
3952  External interface.
3953  Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
3954  ****************************************************************************/
3955
3956 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3957                                           const struct ndr_syntax_id *interface,
3958                                           enum dcerpc_transport_t transport,
3959                                           enum dcerpc_AuthLevel auth_level,
3960                                           const char *domain,
3961                                           const char *username,
3962                                           const char *password,
3963                                           struct rpc_pipe_client **presult)
3964 {
3965         return cli_rpc_pipe_open_ntlmssp_internal(cli,
3966                                                 interface,
3967                                                 transport,
3968                                                 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
3969                                                 auth_level,
3970                                                 domain,
3971                                                 username,
3972                                                 password,
3973                                                 presult);
3974 }
3975
3976 /****************************************************************************
3977   Get a the schannel session key out of an already opened netlogon pipe.
3978  ****************************************************************************/
3979 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
3980                                                 struct cli_state *cli,
3981                                                 const char *domain,
3982                                                 uint32 *pneg_flags)
3983 {
3984         enum netr_SchannelType sec_chan_type = 0;
3985         unsigned char machine_pwd[16];
3986         const char *machine_account;
3987         NTSTATUS status;
3988
3989         /* Get the machine account credentials from secrets.tdb. */
3990         if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
3991                                &sec_chan_type))
3992         {
3993                 DEBUG(0, ("get_schannel_session_key: could not fetch "
3994                         "trust account password for domain '%s'\n",
3995                         domain));
3996                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
3997         }
3998
3999         status = rpccli_netlogon_setup_creds(netlogon_pipe,
4000                                         cli->desthost, /* server name */
4001                                         domain,        /* domain */
4002                                         global_myname(), /* client name */
4003                                         machine_account, /* machine account name */
4004                                         machine_pwd,
4005                                         sec_chan_type,
4006                                         pneg_flags);
4007
4008         if (!NT_STATUS_IS_OK(status)) {
4009                 DEBUG(3, ("get_schannel_session_key_common: "
4010                           "rpccli_netlogon_setup_creds failed with result %s "
4011                           "to server %s, domain %s, machine account %s.\n",
4012                           nt_errstr(status), cli->desthost, domain,
4013                           machine_account ));
4014                 return status;
4015         }
4016
4017         if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
4018                 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
4019                         cli->desthost));
4020                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4021         }
4022
4023         return NT_STATUS_OK;;
4024 }
4025
4026 /****************************************************************************
4027  Open a netlogon pipe and get the schannel session key.
4028  Now exposed to external callers.
4029  ****************************************************************************/
4030
4031
4032 NTSTATUS get_schannel_session_key(struct cli_state *cli,
4033                                   const char *domain,
4034                                   uint32 *pneg_flags,
4035                                   struct rpc_pipe_client **presult)
4036 {
4037         struct rpc_pipe_client *netlogon_pipe = NULL;
4038         NTSTATUS status;
4039
4040         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
4041                                           &netlogon_pipe);
4042         if (!NT_STATUS_IS_OK(status)) {
4043                 return status;
4044         }
4045
4046         status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
4047                                                  pneg_flags);
4048         if (!NT_STATUS_IS_OK(status)) {
4049                 TALLOC_FREE(netlogon_pipe);
4050                 return status;
4051         }
4052
4053         *presult = netlogon_pipe;
4054         return NT_STATUS_OK;
4055 }
4056
4057 /****************************************************************************
4058  External interface.
4059  Open a named pipe to an SMB server and bind using schannel (bind type 68)
4060  using session_key. sign and seal.
4061
4062  The *pdc will be stolen onto this new pipe
4063  ****************************************************************************/
4064
4065 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
4066                                              const struct ndr_syntax_id *interface,
4067                                              enum dcerpc_transport_t transport,
4068                                              enum dcerpc_AuthLevel auth_level,
4069                                              const char *domain,
4070                                              struct netlogon_creds_CredentialState **pdc,
4071                                              struct rpc_pipe_client **presult)
4072 {
4073         struct rpc_pipe_client *result;
4074         struct cli_pipe_auth_data *auth;
4075         NTSTATUS status;
4076
4077         status = cli_rpc_pipe_open(cli, transport, interface, &result);
4078         if (!NT_STATUS_IS_OK(status)) {
4079                 return status;
4080         }
4081
4082         status = rpccli_schannel_bind_data(result, domain, auth_level,
4083                                            *pdc, &auth);
4084         if (!NT_STATUS_IS_OK(status)) {
4085                 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
4086                           nt_errstr(status)));
4087                 TALLOC_FREE(result);
4088                 return status;
4089         }
4090
4091         status = rpc_pipe_bind(result, auth);
4092         if (!NT_STATUS_IS_OK(status)) {
4093                 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
4094                           "cli_rpc_pipe_bind failed with error %s\n",
4095                           nt_errstr(status) ));
4096                 TALLOC_FREE(result);
4097                 return status;
4098         }
4099
4100         /*
4101          * The credentials on a new netlogon pipe are the ones we are passed
4102          * in - reference them in
4103          */
4104         result->dc = talloc_move(result, pdc);
4105
4106         DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
4107                   "for domain %s and bound using schannel.\n",
4108                   get_pipe_name_from_syntax(talloc_tos(), interface),
4109                   cli->desthost, domain ));
4110
4111         *presult = result;
4112         return NT_STATUS_OK;
4113 }
4114
4115 /****************************************************************************
4116  Open a named pipe to an SMB server and bind using schannel (bind type 68).
4117  Fetch the session key ourselves using a temporary netlogon pipe. This
4118  version uses an ntlmssp auth bound netlogon pipe to get the key.
4119  ****************************************************************************/
4120
4121 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
4122                                                       const char *domain,
4123                                                       const char *username,
4124                                                       const char *password,
4125                                                       uint32 *pneg_flags,
4126                                                       struct rpc_pipe_client **presult)
4127 {
4128         struct rpc_pipe_client *netlogon_pipe = NULL;
4129         NTSTATUS status;
4130
4131         status = cli_rpc_pipe_open_spnego_ntlmssp(
4132                 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
4133                 DCERPC_AUTH_LEVEL_PRIVACY,
4134                 domain, username, password, &netlogon_pipe);
4135         if (!NT_STATUS_IS_OK(status)) {
4136                 return status;
4137         }
4138
4139         status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
4140                                                  pneg_flags);
4141         if (!NT_STATUS_IS_OK(status)) {
4142                 TALLOC_FREE(netlogon_pipe);
4143                 return status;
4144         }
4145
4146         *presult = netlogon_pipe;
4147         return NT_STATUS_OK;
4148 }
4149
4150 /****************************************************************************
4151  Open a named pipe to an SMB server and bind using schannel (bind type 68).
4152  Fetch the session key ourselves using a temporary netlogon pipe. This version
4153  uses an ntlmssp bind to get the session key.
4154  ****************************************************************************/
4155
4156 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
4157                                                  const struct ndr_syntax_id *interface,
4158                                                  enum dcerpc_transport_t transport,
4159                                                  enum dcerpc_AuthLevel auth_level,
4160                                                  const char *domain,
4161                                                  const char *username,
4162                                                  const char *password,
4163                                                  struct rpc_pipe_client **presult)
4164 {
4165         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4166         struct rpc_pipe_client *netlogon_pipe = NULL;
4167         struct rpc_pipe_client *result = NULL;
4168         NTSTATUS status;
4169
4170         status = get_schannel_session_key_auth_ntlmssp(
4171                 cli, domain, username, password, &neg_flags, &netlogon_pipe);
4172         if (!NT_STATUS_IS_OK(status)) {
4173                 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
4174                         "key from server %s for domain %s.\n",
4175                         cli->desthost, domain ));
4176                 return status;
4177         }
4178
4179         status = cli_rpc_pipe_open_schannel_with_key(
4180                 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4181                 &result);
4182
4183         /* Now we've bound using the session key we can close the netlog pipe. */
4184         TALLOC_FREE(netlogon_pipe);
4185
4186         if (NT_STATUS_IS_OK(status)) {
4187                 *presult = result;
4188         }
4189         return status;
4190 }
4191
4192 /****************************************************************************
4193  Open a named pipe to an SMB server and bind using schannel (bind type 68).
4194  Fetch the session key ourselves using a temporary netlogon pipe.
4195  ****************************************************************************/
4196
4197 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
4198                                     const struct ndr_syntax_id *interface,
4199                                     enum dcerpc_transport_t transport,
4200                                     enum dcerpc_AuthLevel auth_level,
4201                                     const char *domain,
4202                                     struct rpc_pipe_client **presult)
4203 {
4204         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4205         struct rpc_pipe_client *netlogon_pipe = NULL;
4206         struct rpc_pipe_client *result = NULL;
4207         NTSTATUS status;
4208
4209         status = get_schannel_session_key(cli, domain, &neg_flags,
4210                                           &netlogon_pipe);
4211         if (!NT_STATUS_IS_OK(status)) {
4212                 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
4213                         "key from server %s for domain %s.\n",
4214                         cli->desthost, domain ));
4215                 return status;
4216         }
4217
4218         status = cli_rpc_pipe_open_schannel_with_key(
4219                 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4220                 &result);
4221
4222         /* Now we've bound using the session key we can close the netlog pipe. */
4223         TALLOC_FREE(netlogon_pipe);
4224
4225         if (NT_STATUS_IS_OK(status)) {
4226                 *presult = result;
4227         }
4228
4229         return status;
4230 }
4231
4232 /****************************************************************************
4233  Open a named pipe to an SMB server and bind using krb5 (bind type 16).
4234  The idea is this can be called with service_princ, username and password all
4235  NULL so long as the caller has a TGT.
4236  ****************************************************************************/
4237
4238 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
4239                                 const struct ndr_syntax_id *interface,
4240                                 enum dcerpc_AuthLevel auth_level,
4241                                 const char *service_princ,
4242                                 const char *username,
4243                                 const char *password,
4244                                 struct rpc_pipe_client **presult)
4245 {
4246 #ifdef HAVE_KRB5
4247         struct rpc_pipe_client *result;
4248         struct cli_pipe_auth_data *auth;
4249         NTSTATUS status;
4250
4251         status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
4252         if (!NT_STATUS_IS_OK(status)) {
4253                 return status;
4254         }
4255
4256         status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
4257                                            username, password, &auth);
4258         if (!NT_STATUS_IS_OK(status)) {
4259                 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
4260                           nt_errstr(status)));
4261                 TALLOC_FREE(result);
4262                 return status;
4263         }
4264
4265         status = rpc_pipe_bind(result, auth);
4266         if (!NT_STATUS_IS_OK(status)) {
4267                 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
4268                           "with error %s\n", nt_errstr(status)));
4269                 TALLOC_FREE(result);
4270                 return status;
4271         }
4272
4273         *presult = result;
4274         return NT_STATUS_OK;
4275 #else
4276         DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
4277         return NT_STATUS_NOT_IMPLEMENTED;
4278 #endif
4279 }
4280
4281 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
4282                              struct rpc_pipe_client *cli,
4283                              DATA_BLOB *session_key)
4284 {
4285         if (!session_key || !cli) {
4286                 return NT_STATUS_INVALID_PARAMETER;
4287         }
4288
4289         if (!cli->auth) {
4290                 return NT_STATUS_INVALID_PARAMETER;
4291         }
4292
4293         switch (cli->auth->auth_type) {
4294                 case PIPE_AUTH_TYPE_SCHANNEL:
4295                         *session_key = data_blob_talloc(mem_ctx,
4296                                 cli->auth->a_u.schannel_auth->creds->session_key, 16);
4297                         break;
4298                 case PIPE_AUTH_TYPE_NTLMSSP:
4299                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
4300                         *session_key = data_blob_talloc(mem_ctx,
4301                                 cli->auth->a_u.ntlmssp_state->session_key.data,
4302                                 cli->auth->a_u.ntlmssp_state->session_key.length);
4303                         break;
4304                 case PIPE_AUTH_TYPE_KRB5:
4305                 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
4306                         *session_key = data_blob_talloc(mem_ctx,
4307                                 cli->auth->a_u.kerberos_auth->session_key.data,
4308                                 cli->auth->a_u.kerberos_auth->session_key.length);
4309                         break;
4310                 case PIPE_AUTH_TYPE_NONE:
4311                         *session_key = data_blob_talloc(mem_ctx,
4312                                 cli->auth->user_session_key.data,
4313                                 cli->auth->user_session_key.length);
4314                         break;
4315                 default:
4316                         return NT_STATUS_NO_USER_SESSION_KEY;
4317         }
4318
4319         return NT_STATUS_OK;
4320 }