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