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