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