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