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