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