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