s3-dcerpc: use dcerpc_pull_dcerpc_auth() in rpc_finish_spnego_ntlmssp_bind_send()
[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 *rpc_out)
2135 {
2136         DATA_BLOB auth_info;
2137         NTSTATUS status;
2138         DATA_BLOB auth_blob = data_blob_null;
2139         uint16_t data_and_pad_len =
2140                 prs_offset(rpc_out) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
2141
2142         if (!cli->auth->a_u.ntlmssp_state) {
2143                 return NT_STATUS_INVALID_PARAMETER;
2144         }
2145
2146         switch (cli->auth->auth_level) {
2147         case DCERPC_AUTH_LEVEL_PRIVACY:
2148                 /* Data portion is encrypted. */
2149                 status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
2150                                         prs_get_mem_context(rpc_out),
2151                                         (unsigned char *)prs_data_p(rpc_out)
2152                                                 + RPC_HEADER_LEN
2153                                                 + RPC_HDR_RESP_LEN,
2154                                         data_and_pad_len,
2155                                         (unsigned char *)prs_data_p(rpc_out),
2156                                         (size_t)prs_offset(rpc_out),
2157                                         &auth_blob);
2158                 if (!NT_STATUS_IS_OK(status)) {
2159                         return status;
2160                 }
2161                 break;
2162
2163         case DCERPC_AUTH_LEVEL_INTEGRITY:
2164                 /* Data is signed. */
2165                 status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
2166                                         prs_get_mem_context(rpc_out),
2167                                         (unsigned char *)prs_data_p(rpc_out)
2168                                                 + RPC_HEADER_LEN
2169                                                 + RPC_HDR_RESP_LEN,
2170                                         data_and_pad_len,
2171                                         (unsigned char *)prs_data_p(rpc_out),
2172                                         (size_t)prs_offset(rpc_out),
2173                                         &auth_blob);
2174                 if (!NT_STATUS_IS_OK(status)) {
2175                         return status;
2176                 }
2177                 break;
2178
2179         default:
2180                 /* Can't happen. */
2181                 smb_panic("bad auth level");
2182                 /* Notreached. */
2183                 return NT_STATUS_INVALID_PARAMETER;
2184         }
2185
2186         /* Finally marshall the blob. */
2187         status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
2188                                         map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
2189                                         cli->auth->auth_level,
2190                                         ss_padding_len,
2191                                         1 /* context id. */,
2192                                         &auth_blob,
2193                                         &auth_info);
2194         if (!NT_STATUS_IS_OK(status)) {
2195                 return status;
2196         }
2197
2198         if (!prs_copy_data_in(rpc_out, (const char *)auth_info.data, auth_info.length)) {
2199                 DEBUG(0, ("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
2200                         (unsigned int)auth_info.length));
2201                 return NT_STATUS_NO_MEMORY;
2202         }
2203
2204         return NT_STATUS_OK;
2205 }
2206
2207 /*******************************************************************
2208  Create and add the schannel sign/seal auth header and data.
2209  ********************************************************************/
2210
2211 static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
2212                                         uint32 ss_padding_len,
2213                                         prs_struct *rpc_out)
2214 {
2215         DATA_BLOB auth_info;
2216         struct schannel_state *sas = cli->auth->a_u.schannel_auth;
2217         char *data_p = prs_data_p(rpc_out) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
2218         size_t data_and_pad_len = prs_offset(rpc_out) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
2219         DATA_BLOB blob;
2220         NTSTATUS status;
2221
2222         if (!sas) {
2223                 return NT_STATUS_INVALID_PARAMETER;
2224         }
2225
2226         DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
2227                         sas->seq_num));
2228
2229         switch (cli->auth->auth_level) {
2230         case DCERPC_AUTH_LEVEL_PRIVACY:
2231                 status = netsec_outgoing_packet(sas,
2232                                                 talloc_tos(),
2233                                                 true,
2234                                                 (uint8_t *)data_p,
2235                                                 data_and_pad_len,
2236                                                 &blob);
2237                 break;
2238         case DCERPC_AUTH_LEVEL_INTEGRITY:
2239                 status = netsec_outgoing_packet(sas,
2240                                                 talloc_tos(),
2241                                                 false,
2242                                                 (uint8_t *)data_p,
2243                                                 data_and_pad_len,
2244                                                 &blob);
2245                 break;
2246         default:
2247                 status = NT_STATUS_INTERNAL_ERROR;
2248                 break;
2249         }
2250
2251         if (!NT_STATUS_IS_OK(status)) {
2252                 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
2253                         nt_errstr(status)));
2254                 return status;
2255         }
2256
2257         if (DEBUGLEVEL >= 10) {
2258                 dump_NL_AUTH_SIGNATURE(talloc_tos(), &blob);
2259         }
2260
2261         /* Finally marshall the blob. */
2262         status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
2263                                         map_pipe_auth_type_to_rpc_auth_type(cli->auth->auth_type),
2264                                         cli->auth->auth_level,
2265                                         ss_padding_len,
2266                                         1 /* context id. */,
2267                                         &blob,
2268                                         &auth_info);
2269         if (!NT_STATUS_IS_OK(status)) {
2270                 return status;
2271         }
2272
2273         if (!prs_copy_data_in(rpc_out, (const char *)auth_info.data, auth_info.length)) {
2274                 return NT_STATUS_NO_MEMORY;
2275         }
2276
2277         return NT_STATUS_OK;
2278 }
2279
2280 /*******************************************************************
2281  Calculate how much data we're going to send in this packet, also
2282  work out any sign/seal padding length.
2283  ********************************************************************/
2284
2285 static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
2286                                         uint32 data_left,
2287                                         uint16 *p_frag_len,
2288                                         uint16 *p_auth_len,
2289                                         uint32 *p_ss_padding)
2290 {
2291         uint32 data_space, data_len;
2292
2293 #if 0
2294         if ((data_left > 0) && (sys_random() % 2)) {
2295                 data_left = MAX(data_left/2, 1);
2296         }
2297 #endif
2298
2299         switch (cli->auth->auth_level) {
2300                 case DCERPC_AUTH_LEVEL_NONE:
2301                 case DCERPC_AUTH_LEVEL_CONNECT:
2302                         data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
2303                         data_len = MIN(data_space, data_left);
2304                         *p_ss_padding = 0;
2305                         *p_auth_len = 0;
2306                         *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
2307                         return data_len;
2308
2309                 case DCERPC_AUTH_LEVEL_INTEGRITY:
2310                 case DCERPC_AUTH_LEVEL_PRIVACY:
2311                         /* Treat the same for all authenticated rpc requests. */
2312                         switch(cli->auth->auth_type) {
2313                                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2314                                 case PIPE_AUTH_TYPE_NTLMSSP:
2315                                         *p_auth_len = NTLMSSP_SIG_SIZE;
2316                                         break;
2317                                 case PIPE_AUTH_TYPE_SCHANNEL:
2318                                         *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
2319                                         break;
2320                                 default:
2321                                         smb_panic("bad auth type");
2322                                         break;
2323                         }
2324
2325                         data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
2326                                                 RPC_HDR_AUTH_LEN - *p_auth_len;
2327
2328                         data_len = MIN(data_space, data_left);
2329                         *p_ss_padding = 0;
2330                         if (data_len % CLIENT_NDR_PADDING_SIZE) {
2331                                 *p_ss_padding = CLIENT_NDR_PADDING_SIZE - (data_len % CLIENT_NDR_PADDING_SIZE);
2332                         }
2333                         *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN +                /* Normal headers. */
2334                                         data_len + *p_ss_padding +              /* data plus padding. */
2335                                         RPC_HDR_AUTH_LEN + *p_auth_len;         /* Auth header and auth data. */
2336                         return data_len;
2337
2338                 default:
2339                         smb_panic("bad auth level");
2340                         /* Notreached. */
2341                         return 0;
2342         }
2343 }
2344
2345 /*******************************************************************
2346  External interface.
2347  Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
2348  Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
2349  and deals with signing/sealing details.
2350  ********************************************************************/
2351
2352 struct rpc_api_pipe_req_state {
2353         struct event_context *ev;
2354         struct rpc_pipe_client *cli;
2355         uint8_t op_num;
2356         uint32_t call_id;
2357         prs_struct *req_data;
2358         uint32_t req_data_sent;
2359         prs_struct outgoing_frag;
2360         prs_struct reply_pdu;
2361 };
2362
2363 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
2364 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
2365 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2366                                   bool *is_last_frag);
2367
2368 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
2369                                          struct event_context *ev,
2370                                          struct rpc_pipe_client *cli,
2371                                          uint8_t op_num,
2372                                          prs_struct *req_data)
2373 {
2374         struct tevent_req *req, *subreq;
2375         struct rpc_api_pipe_req_state *state;
2376         NTSTATUS status;
2377         bool is_last_frag;
2378
2379         req = tevent_req_create(mem_ctx, &state,
2380                                 struct rpc_api_pipe_req_state);
2381         if (req == NULL) {
2382                 return NULL;
2383         }
2384         state->ev = ev;
2385         state->cli = cli;
2386         state->op_num = op_num;
2387         state->req_data = req_data;
2388         state->req_data_sent = 0;
2389         state->call_id = get_rpc_call_id();
2390
2391         if (cli->max_xmit_frag
2392             < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
2393                 /* Server is screwed up ! */
2394                 status = NT_STATUS_INVALID_PARAMETER;
2395                 goto post_status;
2396         }
2397
2398         prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2399
2400         if (!prs_init(&state->outgoing_frag, cli->max_xmit_frag,
2401                       state, MARSHALL)) {
2402                 goto fail;
2403         }
2404
2405         status = prepare_next_frag(state, &is_last_frag);
2406         if (!NT_STATUS_IS_OK(status)) {
2407                 goto post_status;
2408         }
2409
2410         if (is_last_frag) {
2411                 subreq = rpc_api_pipe_send(state, ev, state->cli,
2412                                            &state->outgoing_frag,
2413                                            DCERPC_PKT_RESPONSE);
2414                 if (subreq == NULL) {
2415                         goto fail;
2416                 }
2417                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2418         } else {
2419                 subreq = rpc_write_send(
2420                         state, ev, cli->transport,
2421                         (uint8_t *)prs_data_p(&state->outgoing_frag),
2422                         prs_offset(&state->outgoing_frag));
2423                 if (subreq == NULL) {
2424                         goto fail;
2425                 }
2426                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2427                                         req);
2428         }
2429         return req;
2430
2431  post_status:
2432         tevent_req_nterror(req, status);
2433         return tevent_req_post(req, ev);
2434  fail:
2435         TALLOC_FREE(req);
2436         return NULL;
2437 }
2438
2439 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
2440                                   bool *is_last_frag)
2441 {
2442         uint32_t data_sent_thistime;
2443         uint16_t auth_len;
2444         uint16_t frag_len;
2445         uint8_t flags = 0;
2446         uint32_t ss_padding;
2447         uint32_t data_left;
2448         char pad[8] = { 0, };
2449         NTSTATUS status;
2450         union dcerpc_payload u;
2451         DATA_BLOB blob;
2452
2453         data_left = prs_offset(state->req_data) - state->req_data_sent;
2454
2455         data_sent_thistime = calculate_data_len_tosend(
2456                 state->cli, data_left, &frag_len, &auth_len, &ss_padding);
2457
2458         if (state->req_data_sent == 0) {
2459                 flags = DCERPC_PFC_FLAG_FIRST;
2460         }
2461
2462         if (data_sent_thistime == data_left) {
2463                 flags |= DCERPC_PFC_FLAG_LAST;
2464         }
2465
2466         if (!prs_set_offset(&state->outgoing_frag, 0)) {
2467                 return NT_STATUS_NO_MEMORY;
2468         }
2469
2470         ZERO_STRUCT(u.request);
2471
2472         u.request.alloc_hint    = prs_offset(state->req_data);
2473         u.request.context_id    = 0;
2474         u.request.opnum         = state->op_num;
2475
2476         status = dcerpc_push_ncacn_packet(prs_get_mem_context(&state->outgoing_frag),
2477                                           DCERPC_PKT_REQUEST,
2478                                           flags,
2479                                           frag_len,
2480                                           auth_len,
2481                                           state->call_id,
2482                                           u,
2483                                           &blob);
2484         if (!NT_STATUS_IS_OK(status)) {
2485                 return status;
2486         }
2487
2488         if (!prs_copy_data_in(&state->outgoing_frag, (const char *)blob.data, blob.length)) {
2489                 return NT_STATUS_NO_MEMORY;
2490         }
2491
2492         /* Copy in the data, plus any ss padding. */
2493         if (!prs_append_some_prs_data(&state->outgoing_frag,
2494                                       state->req_data, state->req_data_sent,
2495                                       data_sent_thistime)) {
2496                 return NT_STATUS_NO_MEMORY;
2497         }
2498
2499         /* Copy the sign/seal padding data. */
2500         if (!prs_copy_data_in(&state->outgoing_frag, pad, ss_padding)) {
2501                 return NT_STATUS_NO_MEMORY;
2502         }
2503
2504         /* Generate any auth sign/seal and add the auth footer. */
2505         switch (state->cli->auth->auth_type) {
2506         case PIPE_AUTH_TYPE_NONE:
2507                 status = NT_STATUS_OK;
2508                 break;
2509         case PIPE_AUTH_TYPE_NTLMSSP:
2510         case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2511                 status = add_ntlmssp_auth_footer(state->cli, ss_padding,
2512                                                  &state->outgoing_frag);
2513                 break;
2514         case PIPE_AUTH_TYPE_SCHANNEL:
2515                 status = add_schannel_auth_footer(state->cli, ss_padding,
2516                                                   &state->outgoing_frag);
2517                 break;
2518         default:
2519                 status = NT_STATUS_INVALID_PARAMETER;
2520                 break;
2521         }
2522
2523         state->req_data_sent += data_sent_thistime;
2524         *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2525
2526         return status;
2527 }
2528
2529 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
2530 {
2531         struct tevent_req *req = tevent_req_callback_data(
2532                 subreq, struct tevent_req);
2533         struct rpc_api_pipe_req_state *state = tevent_req_data(
2534                 req, struct rpc_api_pipe_req_state);
2535         NTSTATUS status;
2536         bool is_last_frag;
2537
2538         status = rpc_write_recv(subreq);
2539         TALLOC_FREE(subreq);
2540         if (!NT_STATUS_IS_OK(status)) {
2541                 tevent_req_nterror(req, status);
2542                 return;
2543         }
2544
2545         status = prepare_next_frag(state, &is_last_frag);
2546         if (!NT_STATUS_IS_OK(status)) {
2547                 tevent_req_nterror(req, status);
2548                 return;
2549         }
2550
2551         if (is_last_frag) {
2552                 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2553                                            &state->outgoing_frag,
2554                                            DCERPC_PKT_RESPONSE);
2555                 if (tevent_req_nomem(subreq, req)) {
2556                         return;
2557                 }
2558                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
2559         } else {
2560                 subreq = rpc_write_send(
2561                         state, state->ev,
2562                         state->cli->transport,
2563                         (uint8_t *)prs_data_p(&state->outgoing_frag),
2564                         prs_offset(&state->outgoing_frag));
2565                 if (tevent_req_nomem(subreq, req)) {
2566                         return;
2567                 }
2568                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
2569                                         req);
2570         }
2571 }
2572
2573 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
2574 {
2575         struct tevent_req *req = tevent_req_callback_data(
2576                 subreq, struct tevent_req);
2577         struct rpc_api_pipe_req_state *state = tevent_req_data(
2578                 req, struct rpc_api_pipe_req_state);
2579         NTSTATUS status;
2580
2581         status = rpc_api_pipe_recv(subreq, state, &state->reply_pdu);
2582         TALLOC_FREE(subreq);
2583         if (!NT_STATUS_IS_OK(status)) {
2584                 tevent_req_nterror(req, status);
2585                 return;
2586         }
2587         tevent_req_done(req);
2588 }
2589
2590 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2591                                prs_struct *reply_pdu)
2592 {
2593         struct rpc_api_pipe_req_state *state = tevent_req_data(
2594                 req, struct rpc_api_pipe_req_state);
2595         NTSTATUS status;
2596
2597         if (tevent_req_is_nterror(req, &status)) {
2598                 /*
2599                  * We always have to initialize to reply pdu, even if there is
2600                  * none. The rpccli_* caller routines expect this.
2601                  */
2602                 prs_init_empty(reply_pdu, mem_ctx, UNMARSHALL);
2603                 return status;
2604         }
2605
2606         *reply_pdu = state->reply_pdu;
2607         reply_pdu->mem_ctx = mem_ctx;
2608
2609         /*
2610          * Prevent state->req_pdu from being freed
2611          * when state is freed.
2612          */
2613         talloc_steal(mem_ctx, prs_data_p(reply_pdu));
2614         prs_init_empty(&state->reply_pdu, state, UNMARSHALL);
2615
2616         return NT_STATUS_OK;
2617 }
2618
2619 #if 0
2620 /****************************************************************************
2621  Set the handle state.
2622 ****************************************************************************/
2623
2624 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
2625                                    const char *pipe_name, uint16 device_state)
2626 {
2627         bool state_set = False;
2628         char param[2];
2629         uint16 setup[2]; /* only need 2 uint16 setup parameters */
2630         char *rparam = NULL;
2631         char *rdata = NULL;
2632         uint32 rparam_len, rdata_len;
2633
2634         if (pipe_name == NULL)
2635                 return False;
2636
2637         DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
2638                  cli->fnum, pipe_name, device_state));
2639
2640         /* create parameters: device state */
2641         SSVAL(param, 0, device_state);
2642
2643         /* create setup parameters. */
2644         setup[0] = 0x0001; 
2645         setup[1] = cli->fnum; /* pipe file handle.  got this from an SMBOpenX. */
2646
2647         /* send the data on \PIPE\ */
2648         if (cli_api_pipe(cli->cli, "\\PIPE\\",
2649                     setup, 2, 0,                /* setup, length, max */
2650                     param, 2, 0,                /* param, length, max */
2651                     NULL, 0, 1024,              /* data, length, max */
2652                     &rparam, &rparam_len,        /* return param, length */
2653                     &rdata, &rdata_len))         /* return data, length */
2654         {
2655                 DEBUG(5, ("Set Handle state: return OK\n"));
2656                 state_set = True;
2657         }
2658
2659         SAFE_FREE(rparam);
2660         SAFE_FREE(rdata);
2661
2662         return state_set;
2663 }
2664 #endif
2665
2666 /****************************************************************************
2667  Check the rpc bind acknowledge response.
2668 ****************************************************************************/
2669
2670 static bool check_bind_response(const struct dcerpc_bind_ack *r,
2671                                 const struct ndr_syntax_id *transfer)
2672 {
2673         struct dcerpc_ack_ctx ctx;
2674
2675         if (r->secondary_address_size == 0) {
2676                 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
2677         }
2678
2679         if (r->num_results < 1 || !r->ctx_list) {
2680                 return false;
2681         }
2682
2683         ctx = r->ctx_list[0];
2684
2685         /* check the transfer syntax */
2686         if ((ctx.syntax.if_version != transfer->if_version) ||
2687              (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
2688                 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
2689                 return False;
2690         }
2691
2692         if (r->num_results != 0x1 || ctx.result != 0) {
2693                 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
2694                           r->num_results, ctx.reason));
2695         }
2696
2697         DEBUG(5,("check_bind_response: accepted!\n"));
2698         return True;
2699 }
2700
2701 /*******************************************************************
2702  Creates a DCE/RPC bind authentication response.
2703  This is the packet that is sent back to the server once we
2704  have received a BIND-ACK, to finish the third leg of
2705  the authentication handshake.
2706  ********************************************************************/
2707
2708 static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
2709                                 uint32 rpc_call_id,
2710                                 enum pipe_auth_type auth_type,
2711                                 enum dcerpc_AuthLevel auth_level,
2712                                 DATA_BLOB *pauth_blob,
2713                                 prs_struct *rpc_out)
2714 {
2715         uint16_t auth_len = pauth_blob->length;
2716         uint16_t frag_len = 0;
2717         NTSTATUS status;
2718         union dcerpc_payload u;
2719         DATA_BLOB blob;
2720
2721         u.auth3._pad = 0;
2722
2723         status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
2724                         map_pipe_auth_type_to_rpc_auth_type(auth_type),
2725                                          auth_level,
2726                                          0, /* auth_pad_length */
2727                                          1, /* auth_context_id */
2728                                          pauth_blob,
2729                                          &u.auth3.auth_info);
2730         if (!NT_STATUS_IS_OK(status)) {
2731                 return status;
2732         }
2733
2734         /* Start building the frag length. */
2735         frag_len = RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + auth_len;
2736
2737         status = dcerpc_push_ncacn_packet(prs_get_mem_context(rpc_out),
2738                                           DCERPC_PKT_AUTH3,
2739                                           DCERPC_PFC_FLAG_FIRST |
2740                                           DCERPC_PFC_FLAG_LAST,
2741                                           frag_len,
2742                                           auth_len ? auth_len - RPC_HDR_AUTH_LEN : 0,
2743                                           rpc_call_id,
2744                                           u,
2745                                           &blob);
2746         if (!NT_STATUS_IS_OK(status)) {
2747                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
2748                 return status;
2749         }
2750
2751         if (!prs_copy_data_in(rpc_out, (char *)blob.data, blob.length)) {
2752                 return NT_STATUS_NO_MEMORY;
2753         }
2754
2755         return NT_STATUS_OK;
2756 }
2757
2758 /*******************************************************************
2759  Creates a DCE/RPC bind alter context authentication request which
2760  may contain a spnego auth blobl
2761  ********************************************************************/
2762
2763 static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
2764                                         const struct ndr_syntax_id *abstract,
2765                                         const struct ndr_syntax_id *transfer,
2766                                         enum dcerpc_AuthLevel auth_level,
2767                                         const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
2768                                         prs_struct *rpc_out)
2769 {
2770         DATA_BLOB auth_info;
2771         NTSTATUS status;
2772
2773         status = dcerpc_push_dcerpc_auth(prs_get_mem_context(rpc_out),
2774                                          DCERPC_AUTH_TYPE_SPNEGO,
2775                                          auth_level,
2776                                          0, /* auth_pad_length */
2777                                          1, /* auth_context_id */
2778                                          pauth_blob,
2779                                          &auth_info);
2780         if (!NT_STATUS_IS_OK(status)) {
2781                 return status;
2782         }
2783
2784
2785         status = create_bind_or_alt_ctx_internal(DCERPC_PKT_ALTER,
2786                                                  rpc_out,
2787                                                  rpc_call_id,
2788                                                  abstract,
2789                                                  transfer,
2790                                                  &auth_info);
2791         if (!NT_STATUS_IS_OK(status)) {
2792                 return status;
2793         }
2794
2795         return status;
2796 }
2797
2798 /****************************************************************************
2799  Do an rpc bind.
2800 ****************************************************************************/
2801
2802 struct rpc_pipe_bind_state {
2803         struct event_context *ev;
2804         struct rpc_pipe_client *cli;
2805         prs_struct rpc_out;
2806         uint32_t rpc_call_id;
2807 };
2808
2809 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
2810 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2811                                            struct rpc_pipe_bind_state *state,
2812                                            struct ncacn_packet *r,
2813                                            prs_struct *reply_pdu);
2814 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
2815 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
2816                                                     struct rpc_pipe_bind_state *state,
2817                                                     struct ncacn_packet *r,
2818                                                     prs_struct *reply_pdu);
2819 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
2820
2821 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
2822                                       struct event_context *ev,
2823                                       struct rpc_pipe_client *cli,
2824                                       struct cli_pipe_auth_data *auth)
2825 {
2826         struct tevent_req *req, *subreq;
2827         struct rpc_pipe_bind_state *state;
2828         NTSTATUS status;
2829
2830         req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
2831         if (req == NULL) {
2832                 return NULL;
2833         }
2834
2835         DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
2836                 rpccli_pipe_txt(talloc_tos(), cli),
2837                 (unsigned int)auth->auth_type,
2838                 (unsigned int)auth->auth_level ));
2839
2840         state->ev = ev;
2841         state->cli = cli;
2842         state->rpc_call_id = get_rpc_call_id();
2843
2844         prs_init_empty(&state->rpc_out, state, MARSHALL);
2845
2846         cli->auth = talloc_move(cli, &auth);
2847
2848         /* Marshall the outgoing data. */
2849         status = create_rpc_bind_req(cli, &state->rpc_out,
2850                                      state->rpc_call_id,
2851                                      &cli->abstract_syntax,
2852                                      &cli->transfer_syntax,
2853                                      cli->auth->auth_type,
2854                                      cli->auth->auth_level);
2855
2856         if (!NT_STATUS_IS_OK(status)) {
2857                 goto post_status;
2858         }
2859
2860         subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
2861                                    DCERPC_PKT_BIND_ACK);
2862         if (subreq == NULL) {
2863                 goto fail;
2864         }
2865         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2866         return req;
2867
2868  post_status:
2869         tevent_req_nterror(req, status);
2870         return tevent_req_post(req, ev);
2871  fail:
2872         TALLOC_FREE(req);
2873         return NULL;
2874 }
2875
2876 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
2877 {
2878         struct tevent_req *req = tevent_req_callback_data(
2879                 subreq, struct tevent_req);
2880         struct rpc_pipe_bind_state *state = tevent_req_data(
2881                 req, struct rpc_pipe_bind_state);
2882         prs_struct reply_pdu;
2883         DATA_BLOB blob;
2884         struct ncacn_packet r;
2885         NTSTATUS status;
2886
2887         status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu);
2888         TALLOC_FREE(subreq);
2889         if (!NT_STATUS_IS_OK(status)) {
2890                 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
2891                           rpccli_pipe_txt(talloc_tos(), state->cli),
2892                           nt_errstr(status)));
2893                 tevent_req_nterror(req, status);
2894                 return;
2895         }
2896
2897         blob = data_blob_const(prs_data_p(&reply_pdu),
2898                                prs_data_size(&reply_pdu));
2899
2900         status = dcerpc_pull_ncacn_packet(talloc_tos(), &blob, &r);
2901         if (!NT_STATUS_IS_OK(status)) {
2902                 tevent_req_nterror(req, status);
2903                 return;
2904         }
2905
2906         if (!check_bind_response(&r.u.bind_ack, &state->cli->transfer_syntax)) {
2907                 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
2908                 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2909                 return;
2910         }
2911
2912         state->cli->max_xmit_frag = r.u.bind_ack.max_xmit_frag;
2913         state->cli->max_recv_frag = r.u.bind_ack.max_recv_frag;
2914
2915         /*
2916          * For authenticated binds we may need to do 3 or 4 leg binds.
2917          */
2918
2919         switch(state->cli->auth->auth_type) {
2920
2921         case PIPE_AUTH_TYPE_NONE:
2922         case PIPE_AUTH_TYPE_SCHANNEL:
2923                 /* Bind complete. */
2924                 tevent_req_done(req);
2925                 break;
2926
2927         case PIPE_AUTH_TYPE_NTLMSSP:
2928                 /* Need to send AUTH3 packet - no reply. */
2929                 status = rpc_finish_auth3_bind_send(req, state, &r,
2930                                                     &reply_pdu);
2931                 if (!NT_STATUS_IS_OK(status)) {
2932                         tevent_req_nterror(req, status);
2933                 }
2934                 break;
2935
2936         case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
2937                 /* Need to send alter context request and reply. */
2938                 status = rpc_finish_spnego_ntlmssp_bind_send(req, state, &r,
2939                                                              &reply_pdu);
2940                 if (!NT_STATUS_IS_OK(status)) {
2941                         tevent_req_nterror(req, status);
2942                 }
2943                 break;
2944
2945         case PIPE_AUTH_TYPE_KRB5:
2946                 /* */
2947
2948         default:
2949                 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
2950                          (unsigned int)state->cli->auth->auth_type));
2951                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2952         }
2953 }
2954
2955 static NTSTATUS rpc_finish_auth3_bind_send(struct tevent_req *req,
2956                                            struct rpc_pipe_bind_state *state,
2957                                            struct ncacn_packet *r,
2958                                            prs_struct *reply_pdu)
2959 {
2960         DATA_BLOB server_response = data_blob_null;
2961         DATA_BLOB client_reply = data_blob_null;
2962         struct rpc_hdr_auth_info hdr_auth;
2963         struct tevent_req *subreq;
2964         NTSTATUS status;
2965
2966         if ((r->auth_length == 0)
2967             || (r->frag_length < r->auth_length + RPC_HDR_AUTH_LEN)) {
2968                 return NT_STATUS_INVALID_PARAMETER;
2969         }
2970
2971         if (!prs_set_offset(
2972                     reply_pdu,
2973                     r->frag_length - r->auth_length - RPC_HDR_AUTH_LEN)) {
2974                 return NT_STATUS_INVALID_PARAMETER;
2975         }
2976
2977         if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, reply_pdu, 0)) {
2978                 return NT_STATUS_INVALID_PARAMETER;
2979         }
2980
2981         /* TODO - check auth_type/auth_level match. */
2982
2983         server_response = data_blob_talloc(talloc_tos(), NULL, r->auth_length);
2984         prs_copy_data_out((char *)server_response.data, reply_pdu,
2985                           r->auth_length);
2986
2987         status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
2988                                 server_response, &client_reply);
2989
2990         if (!NT_STATUS_IS_OK(status)) {
2991                 DEBUG(0, ("rpc_finish_auth3_bind: NTLMSSP update using server "
2992                           "blob failed: %s.\n", nt_errstr(status)));
2993                 return status;
2994         }
2995
2996         prs_init_empty(&state->rpc_out, talloc_tos(), MARSHALL);
2997
2998         status = create_rpc_bind_auth3(state->cli, state->rpc_call_id,
2999                                        state->cli->auth->auth_type,
3000                                        state->cli->auth->auth_level,
3001                                        &client_reply, &state->rpc_out);
3002         data_blob_free(&client_reply);
3003
3004         if (!NT_STATUS_IS_OK(status)) {
3005                 return status;
3006         }
3007
3008         subreq = rpc_write_send(state, state->ev, state->cli->transport,
3009                                 (uint8_t *)prs_data_p(&state->rpc_out),
3010                                 prs_offset(&state->rpc_out));
3011         if (subreq == NULL) {
3012                 return NT_STATUS_NO_MEMORY;
3013         }
3014         tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
3015         return NT_STATUS_OK;
3016 }
3017
3018 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
3019 {
3020         struct tevent_req *req = tevent_req_callback_data(
3021                 subreq, struct tevent_req);
3022         NTSTATUS status;
3023
3024         status = rpc_write_recv(subreq);
3025         TALLOC_FREE(subreq);
3026         if (!NT_STATUS_IS_OK(status)) {
3027                 tevent_req_nterror(req, status);
3028                 return;
3029         }
3030         tevent_req_done(req);
3031 }
3032
3033 static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
3034                                                     struct rpc_pipe_bind_state *state,
3035                                                     struct ncacn_packet *r,
3036                                                     prs_struct *rpc_in)
3037 {
3038         DATA_BLOB server_ntlm_response = data_blob_null;
3039         DATA_BLOB client_reply = data_blob_null;
3040         DATA_BLOB tmp_blob = data_blob_null;
3041         struct dcerpc_auth auth_info;
3042         DATA_BLOB auth_blob;
3043         struct tevent_req *subreq;
3044         NTSTATUS status;
3045
3046         if ((r->auth_length == 0)
3047             || (r->frag_length < r->auth_length + RPC_HDR_AUTH_LEN)) {
3048                 return NT_STATUS_INVALID_PARAMETER;
3049         }
3050
3051         /* Process the returned NTLMSSP blob first. */
3052         if (!prs_set_offset(
3053                     rpc_in,
3054                     r->frag_length - r->auth_length - RPC_HDR_AUTH_LEN)) {
3055                 return NT_STATUS_INVALID_PARAMETER;
3056         }
3057
3058         auth_blob = data_blob_const(prs_data_p(rpc_in) + prs_offset(rpc_in),
3059                                     prs_data_size(rpc_in) - prs_offset(rpc_in));
3060
3061         status = dcerpc_pull_dcerpc_auth(state, &auth_blob, &auth_info);
3062         if (!NT_STATUS_IS_OK(status)) {
3063                 DEBUG(0, ("Failed to unmarshall dcerpc_auth.\n"));
3064                 return status;
3065         }
3066
3067         /*
3068          * The server might give us back two challenges - tmp_blob is for the
3069          * second.
3070          */
3071         if (!spnego_parse_challenge(auth_info.credentials,
3072                                     &server_ntlm_response, &tmp_blob)) {
3073                 data_blob_free(&server_ntlm_response);
3074                 data_blob_free(&tmp_blob);
3075                 return NT_STATUS_INVALID_PARAMETER;
3076         }
3077
3078         /* We're finished with the server spnego response and the tmp_blob. */
3079         data_blob_free(&tmp_blob);
3080
3081         status = ntlmssp_update(state->cli->auth->a_u.ntlmssp_state,
3082                                 server_ntlm_response, &client_reply);
3083
3084         /* Finished with the server_ntlm response */
3085         data_blob_free(&server_ntlm_response);
3086
3087         if (!NT_STATUS_IS_OK(status)) {
3088                 DEBUG(0, ("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update "
3089                           "using server blob failed.\n"));
3090                 data_blob_free(&client_reply);
3091                 return status;
3092         }
3093
3094         /* SPNEGO wrap the client reply. */
3095         tmp_blob = spnego_gen_auth(client_reply);
3096         data_blob_free(&client_reply);
3097         client_reply = tmp_blob;
3098         tmp_blob = data_blob_null;
3099
3100         /* Now prepare the alter context pdu. */
3101         prs_init_empty(&state->rpc_out, state, MARSHALL);
3102
3103         status = create_rpc_alter_context(state->rpc_call_id,
3104                                           &state->cli->abstract_syntax,
3105                                           &state->cli->transfer_syntax,
3106                                           state->cli->auth->auth_level,
3107                                           &client_reply,
3108                                           &state->rpc_out);
3109         data_blob_free(&client_reply);
3110
3111         if (!NT_STATUS_IS_OK(status)) {
3112                 return status;
3113         }
3114
3115         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
3116                                    &state->rpc_out, DCERPC_PKT_ALTER_RESP);
3117         if (subreq == NULL) {
3118                 return NT_STATUS_NO_MEMORY;
3119         }
3120         tevent_req_set_callback(subreq, rpc_bind_ntlmssp_api_done, req);
3121         return NT_STATUS_OK;
3122 }
3123
3124 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
3125 {
3126         struct tevent_req *req = tevent_req_callback_data(
3127                 subreq, struct tevent_req);
3128         struct rpc_pipe_bind_state *state = tevent_req_data(
3129                 req, struct rpc_pipe_bind_state);
3130         DATA_BLOB server_spnego_response = data_blob_null;
3131         DATA_BLOB tmp_blob = data_blob_null;
3132         prs_struct reply_pdu;
3133         struct ncacn_packet_header hdr;
3134         struct rpc_hdr_auth_info hdr_auth;
3135         NTSTATUS status;
3136
3137         status = rpc_api_pipe_recv(subreq, talloc_tos(), &reply_pdu);
3138         TALLOC_FREE(subreq);
3139         if (!NT_STATUS_IS_OK(status)) {
3140                 tevent_req_nterror(req, status);
3141                 return;
3142         }
3143
3144         status = parse_rpc_header(state->cli, &hdr, &reply_pdu);
3145         if (!NT_STATUS_IS_OK(status)) {
3146                 tevent_req_nterror(req, status);
3147                 return;
3148         }
3149
3150         if (!prs_set_offset(
3151                     &reply_pdu,
3152                     hdr.frag_length - hdr.auth_length - RPC_HDR_AUTH_LEN)) {
3153                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
3154                 return;
3155         }
3156
3157         if (!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &reply_pdu, 0)) {
3158                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
3159                 return;
3160         }
3161
3162         server_spnego_response = data_blob(NULL, hdr.auth_length);
3163         prs_copy_data_out((char *)server_spnego_response.data, &reply_pdu,
3164                           hdr.auth_length);
3165
3166         /* Check we got a valid auth response. */
3167         if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK,
3168                                         OID_NTLMSSP, &tmp_blob)) {
3169                 data_blob_free(&server_spnego_response);
3170                 data_blob_free(&tmp_blob);
3171                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
3172                 return;
3173         }
3174
3175         data_blob_free(&server_spnego_response);
3176         data_blob_free(&tmp_blob);
3177
3178         DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
3179                  "%s.\n", rpccli_pipe_txt(talloc_tos(), state->cli)));
3180         tevent_req_done(req);
3181 }
3182
3183 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
3184 {
3185         return tevent_req_simple_recv_ntstatus(req);
3186 }
3187
3188 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
3189                        struct cli_pipe_auth_data *auth)
3190 {
3191         TALLOC_CTX *frame = talloc_stackframe();
3192         struct event_context *ev;
3193         struct tevent_req *req;
3194         NTSTATUS status = NT_STATUS_OK;
3195
3196         ev = event_context_init(frame);
3197         if (ev == NULL) {
3198                 status = NT_STATUS_NO_MEMORY;
3199                 goto fail;
3200         }
3201
3202         req = rpc_pipe_bind_send(frame, ev, cli, auth);
3203         if (req == NULL) {
3204                 status = NT_STATUS_NO_MEMORY;
3205                 goto fail;
3206         }
3207
3208         if (!tevent_req_poll(req, ev)) {
3209                 status = map_nt_error_from_unix(errno);
3210                 goto fail;
3211         }
3212
3213         status = rpc_pipe_bind_recv(req);
3214  fail:
3215         TALLOC_FREE(frame);
3216         return status;
3217 }
3218
3219 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
3220
3221 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
3222                                 unsigned int timeout)
3223 {
3224         unsigned int old;
3225
3226         if (rpc_cli->transport == NULL) {
3227                 return RPCCLI_DEFAULT_TIMEOUT;
3228         }
3229
3230         if (rpc_cli->transport->set_timeout == NULL) {
3231                 return RPCCLI_DEFAULT_TIMEOUT;
3232         }
3233
3234         old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
3235         if (old == 0) {
3236                 return RPCCLI_DEFAULT_TIMEOUT;
3237         }
3238
3239         return old;
3240 }
3241
3242 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
3243 {
3244         if (rpc_cli == NULL) {
3245                 return false;
3246         }
3247
3248         if (rpc_cli->transport == NULL) {
3249                 return false;
3250         }
3251
3252         return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
3253 }
3254
3255 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
3256 {
3257         struct cli_state *cli;
3258
3259         if ((rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_NTLMSSP)
3260             || (rpc_cli->auth->auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP)) {
3261                 memcpy(nt_hash, rpc_cli->auth->a_u.ntlmssp_state->nt_hash, 16);
3262                 return true;
3263         }
3264
3265         cli = rpc_pipe_np_smb_conn(rpc_cli);
3266         if (cli == NULL) {
3267                 return false;
3268         }
3269         E_md4hash(cli->password ? cli->password : "", nt_hash);
3270         return true;
3271 }
3272
3273 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
3274                                struct cli_pipe_auth_data **presult)
3275 {
3276         struct cli_pipe_auth_data *result;
3277
3278         result = talloc(mem_ctx, struct cli_pipe_auth_data);
3279         if (result == NULL) {
3280                 return NT_STATUS_NO_MEMORY;
3281         }
3282
3283         result->auth_type = PIPE_AUTH_TYPE_NONE;
3284         result->auth_level = DCERPC_AUTH_LEVEL_NONE;
3285
3286         result->user_name = talloc_strdup(result, "");
3287         result->domain = talloc_strdup(result, "");
3288         if ((result->user_name == NULL) || (result->domain == NULL)) {
3289                 TALLOC_FREE(result);
3290                 return NT_STATUS_NO_MEMORY;
3291         }
3292
3293         *presult = result;
3294         return NT_STATUS_OK;
3295 }
3296
3297 static int cli_auth_ntlmssp_data_destructor(struct cli_pipe_auth_data *auth)
3298 {
3299         ntlmssp_end(&auth->a_u.ntlmssp_state);
3300         return 0;
3301 }
3302
3303 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
3304                                   enum pipe_auth_type auth_type,
3305                                   enum dcerpc_AuthLevel auth_level,
3306                                   const char *domain,
3307                                   const char *username,
3308                                   const char *password,
3309                                   struct cli_pipe_auth_data **presult)
3310 {
3311         struct cli_pipe_auth_data *result;
3312         NTSTATUS status;
3313
3314         result = talloc(mem_ctx, struct cli_pipe_auth_data);
3315         if (result == NULL) {
3316                 return NT_STATUS_NO_MEMORY;
3317         }
3318
3319         result->auth_type = auth_type;
3320         result->auth_level = auth_level;
3321
3322         result->user_name = talloc_strdup(result, username);
3323         result->domain = talloc_strdup(result, domain);
3324         if ((result->user_name == NULL) || (result->domain == NULL)) {
3325                 status = NT_STATUS_NO_MEMORY;
3326                 goto fail;
3327         }
3328
3329         status = ntlmssp_client_start(NULL,
3330                                       global_myname(),
3331                                       lp_workgroup(),
3332                                       lp_client_ntlmv2_auth(),
3333                                       &result->a_u.ntlmssp_state);
3334         if (!NT_STATUS_IS_OK(status)) {
3335                 goto fail;
3336         }
3337
3338         talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
3339
3340         status = ntlmssp_set_username(result->a_u.ntlmssp_state, username);
3341         if (!NT_STATUS_IS_OK(status)) {
3342                 goto fail;
3343         }
3344
3345         status = ntlmssp_set_domain(result->a_u.ntlmssp_state, domain);
3346         if (!NT_STATUS_IS_OK(status)) {
3347                 goto fail;
3348         }
3349
3350         status = ntlmssp_set_password(result->a_u.ntlmssp_state, password);
3351         if (!NT_STATUS_IS_OK(status)) {
3352                 goto fail;
3353         }
3354
3355         /*
3356          * Turn off sign+seal to allow selected auth level to turn it back on.
3357          */
3358         result->a_u.ntlmssp_state->neg_flags &=
3359                 ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL);
3360
3361         if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
3362                 result->a_u.ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
3363         } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
3364                 result->a_u.ntlmssp_state->neg_flags
3365                         |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
3366         }
3367
3368         *presult = result;
3369         return NT_STATUS_OK;
3370
3371  fail:
3372         TALLOC_FREE(result);
3373         return status;
3374 }
3375
3376 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
3377                                    enum dcerpc_AuthLevel auth_level,
3378                                    struct netlogon_creds_CredentialState *creds,
3379                                    struct cli_pipe_auth_data **presult)
3380 {
3381         struct cli_pipe_auth_data *result;
3382
3383         result = talloc(mem_ctx, struct cli_pipe_auth_data);
3384         if (result == NULL) {
3385                 return NT_STATUS_NO_MEMORY;
3386         }
3387
3388         result->auth_type = PIPE_AUTH_TYPE_SCHANNEL;
3389         result->auth_level = auth_level;
3390
3391         result->user_name = talloc_strdup(result, "");
3392         result->domain = talloc_strdup(result, domain);
3393         if ((result->user_name == NULL) || (result->domain == NULL)) {
3394                 goto fail;
3395         }
3396
3397         result->a_u.schannel_auth = talloc(result, struct schannel_state);
3398         if (result->a_u.schannel_auth == NULL) {
3399                 goto fail;
3400         }
3401
3402         result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
3403         result->a_u.schannel_auth->seq_num = 0;
3404         result->a_u.schannel_auth->initiator = true;
3405         result->a_u.schannel_auth->creds = creds;
3406
3407         *presult = result;
3408         return NT_STATUS_OK;
3409
3410  fail:
3411         TALLOC_FREE(result);
3412         return NT_STATUS_NO_MEMORY;
3413 }
3414
3415 #ifdef HAVE_KRB5
3416 static int cli_auth_kerberos_data_destructor(struct kerberos_auth_struct *auth)
3417 {
3418         data_blob_free(&auth->session_key);
3419         return 0;
3420 }
3421 #endif
3422
3423 static NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
3424                                    enum dcerpc_AuthLevel auth_level,
3425                                    const char *service_princ,
3426                                    const char *username,
3427                                    const char *password,
3428                                    struct cli_pipe_auth_data **presult)
3429 {
3430 #ifdef HAVE_KRB5
3431         struct cli_pipe_auth_data *result;
3432
3433         if ((username != NULL) && (password != NULL)) {
3434                 int ret = kerberos_kinit_password(username, password, 0, NULL);
3435                 if (ret != 0) {
3436                         return NT_STATUS_ACCESS_DENIED;
3437                 }
3438         }
3439
3440         result = talloc(mem_ctx, struct cli_pipe_auth_data);
3441         if (result == NULL) {
3442                 return NT_STATUS_NO_MEMORY;
3443         }
3444
3445         result->auth_type = PIPE_AUTH_TYPE_KRB5;
3446         result->auth_level = auth_level;
3447
3448         /*
3449          * Username / domain need fixing!
3450          */
3451         result->user_name = talloc_strdup(result, "");
3452         result->domain = talloc_strdup(result, "");
3453         if ((result->user_name == NULL) || (result->domain == NULL)) {
3454                 goto fail;
3455         }
3456
3457         result->a_u.kerberos_auth = TALLOC_ZERO_P(
3458                 result, struct kerberos_auth_struct);
3459         if (result->a_u.kerberos_auth == NULL) {
3460                 goto fail;
3461         }
3462         talloc_set_destructor(result->a_u.kerberos_auth,
3463                               cli_auth_kerberos_data_destructor);
3464
3465         result->a_u.kerberos_auth->service_principal = talloc_strdup(
3466                 result, service_princ);
3467         if (result->a_u.kerberos_auth->service_principal == NULL) {
3468                 goto fail;
3469         }
3470
3471         *presult = result;
3472         return NT_STATUS_OK;
3473
3474  fail:
3475         TALLOC_FREE(result);
3476         return NT_STATUS_NO_MEMORY;
3477 #else
3478         return NT_STATUS_NOT_SUPPORTED;
3479 #endif
3480 }
3481
3482 /**
3483  * Create an rpc pipe client struct, connecting to a tcp port.
3484  */
3485 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
3486                                        uint16_t port,
3487                                        const struct ndr_syntax_id *abstract_syntax,
3488                                        struct rpc_pipe_client **presult)
3489 {
3490         struct rpc_pipe_client *result;
3491         struct sockaddr_storage addr;
3492         NTSTATUS status;
3493         int fd;
3494
3495         result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
3496         if (result == NULL) {
3497                 return NT_STATUS_NO_MEMORY;
3498         }
3499
3500         result->abstract_syntax = *abstract_syntax;
3501         result->transfer_syntax = ndr_transfer_syntax;
3502         result->dispatch = cli_do_rpc_ndr;
3503         result->dispatch_send = cli_do_rpc_ndr_send;
3504         result->dispatch_recv = cli_do_rpc_ndr_recv;
3505
3506         result->desthost = talloc_strdup(result, host);
3507         result->srv_name_slash = talloc_asprintf_strupper_m(
3508                 result, "\\\\%s", result->desthost);
3509         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3510                 status = NT_STATUS_NO_MEMORY;
3511                 goto fail;
3512         }
3513
3514         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3515         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3516
3517         if (!resolve_name(host, &addr, 0, false)) {
3518                 status = NT_STATUS_NOT_FOUND;
3519                 goto fail;
3520         }
3521
3522         status = open_socket_out(&addr, port, 60, &fd);
3523         if (!NT_STATUS_IS_OK(status)) {
3524                 goto fail;
3525         }
3526         set_socket_options(fd, lp_socket_options());
3527
3528         status = rpc_transport_sock_init(result, fd, &result->transport);
3529         if (!NT_STATUS_IS_OK(status)) {
3530                 close(fd);
3531                 goto fail;
3532         }
3533
3534         result->transport->transport = NCACN_IP_TCP;
3535
3536         *presult = result;
3537         return NT_STATUS_OK;
3538
3539  fail:
3540         TALLOC_FREE(result);
3541         return status;
3542 }
3543
3544 /**
3545  * Determine the tcp port on which a dcerpc interface is listening
3546  * for the ncacn_ip_tcp transport via the endpoint mapper of the
3547  * target host.
3548  */
3549 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
3550                                       const struct ndr_syntax_id *abstract_syntax,
3551                                       uint16_t *pport)
3552 {
3553         NTSTATUS status;
3554         struct rpc_pipe_client *epm_pipe = NULL;
3555         struct cli_pipe_auth_data *auth = NULL;
3556         struct dcerpc_binding *map_binding = NULL;
3557         struct dcerpc_binding *res_binding = NULL;
3558         struct epm_twr_t *map_tower = NULL;
3559         struct epm_twr_t *res_towers = NULL;
3560         struct policy_handle *entry_handle = NULL;
3561         uint32_t num_towers = 0;
3562         uint32_t max_towers = 1;
3563         struct epm_twr_p_t towers;
3564         TALLOC_CTX *tmp_ctx = talloc_stackframe();
3565
3566         if (pport == NULL) {
3567                 status = NT_STATUS_INVALID_PARAMETER;
3568                 goto done;
3569         }
3570
3571         /* open the connection to the endpoint mapper */
3572         status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
3573                                         &ndr_table_epmapper.syntax_id,
3574                                         &epm_pipe);
3575
3576         if (!NT_STATUS_IS_OK(status)) {
3577                 goto done;
3578         }
3579
3580         status = rpccli_anon_bind_data(tmp_ctx, &auth);
3581         if (!NT_STATUS_IS_OK(status)) {
3582                 goto done;
3583         }
3584
3585         status = rpc_pipe_bind(epm_pipe, auth);
3586         if (!NT_STATUS_IS_OK(status)) {
3587                 goto done;
3588         }
3589
3590         /* create tower for asking the epmapper */
3591
3592         map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
3593         if (map_binding == NULL) {
3594                 status = NT_STATUS_NO_MEMORY;
3595                 goto done;
3596         }
3597
3598         map_binding->transport = NCACN_IP_TCP;
3599         map_binding->object = *abstract_syntax;
3600         map_binding->host = host; /* needed? */
3601         map_binding->endpoint = "0"; /* correct? needed? */
3602
3603         map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
3604         if (map_tower == NULL) {
3605                 status = NT_STATUS_NO_MEMORY;
3606                 goto done;
3607         }
3608
3609         status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
3610                                             &(map_tower->tower));
3611         if (!NT_STATUS_IS_OK(status)) {
3612                 goto done;
3613         }
3614
3615         /* allocate further parameters for the epm_Map call */
3616
3617         res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
3618         if (res_towers == NULL) {
3619                 status = NT_STATUS_NO_MEMORY;
3620                 goto done;
3621         }
3622         towers.twr = res_towers;
3623
3624         entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
3625         if (entry_handle == NULL) {
3626                 status = NT_STATUS_NO_MEMORY;
3627                 goto done;
3628         }
3629
3630         /* ask the endpoint mapper for the port */
3631
3632         status = rpccli_epm_Map(epm_pipe,
3633                                 tmp_ctx,
3634                                 CONST_DISCARD(struct GUID *,
3635                                               &(abstract_syntax->uuid)),
3636                                 map_tower,
3637                                 entry_handle,
3638                                 max_towers,
3639                                 &num_towers,
3640                                 &towers);
3641
3642         if (!NT_STATUS_IS_OK(status)) {
3643                 goto done;
3644         }
3645
3646         if (num_towers != 1) {
3647                 status = NT_STATUS_UNSUCCESSFUL;
3648                 goto done;
3649         }
3650
3651         /* extract the port from the answer */
3652
3653         status = dcerpc_binding_from_tower(tmp_ctx,
3654                                            &(towers.twr->tower),
3655                                            &res_binding);
3656         if (!NT_STATUS_IS_OK(status)) {
3657                 goto done;
3658         }
3659
3660         /* are further checks here necessary? */
3661         if (res_binding->transport != NCACN_IP_TCP) {
3662                 status = NT_STATUS_UNSUCCESSFUL;
3663                 goto done;
3664         }
3665
3666         *pport = (uint16_t)atoi(res_binding->endpoint);
3667
3668 done:
3669         TALLOC_FREE(tmp_ctx);
3670         return status;
3671 }
3672
3673 /**
3674  * Create a rpc pipe client struct, connecting to a host via tcp.
3675  * The port is determined by asking the endpoint mapper on the given
3676  * host.
3677  */
3678 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
3679                            const struct ndr_syntax_id *abstract_syntax,
3680                            struct rpc_pipe_client **presult)
3681 {
3682         NTSTATUS status;
3683         uint16_t port = 0;
3684
3685         status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
3686         if (!NT_STATUS_IS_OK(status)) {
3687                 return status;
3688         }
3689
3690         return rpc_pipe_open_tcp_port(mem_ctx, host, port,
3691                                         abstract_syntax, presult);
3692 }
3693
3694 /********************************************************************
3695  Create a rpc pipe client struct, connecting to a unix domain socket
3696  ********************************************************************/
3697 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
3698                                const struct ndr_syntax_id *abstract_syntax,
3699                                struct rpc_pipe_client **presult)
3700 {
3701         struct rpc_pipe_client *result;
3702         struct sockaddr_un addr;
3703         NTSTATUS status;
3704         int fd;
3705
3706         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3707         if (result == NULL) {
3708                 return NT_STATUS_NO_MEMORY;
3709         }
3710
3711         result->abstract_syntax = *abstract_syntax;
3712         result->transfer_syntax = ndr_transfer_syntax;
3713         result->dispatch = cli_do_rpc_ndr;
3714         result->dispatch_send = cli_do_rpc_ndr_send;
3715         result->dispatch_recv = cli_do_rpc_ndr_recv;
3716
3717         result->desthost = get_myname(result);
3718         result->srv_name_slash = talloc_asprintf_strupper_m(
3719                 result, "\\\\%s", result->desthost);
3720         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3721                 status = NT_STATUS_NO_MEMORY;
3722                 goto fail;
3723         }
3724
3725         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3726         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3727
3728         fd = socket(AF_UNIX, SOCK_STREAM, 0);
3729         if (fd == -1) {
3730                 status = map_nt_error_from_unix(errno);
3731                 goto fail;
3732         }
3733
3734         ZERO_STRUCT(addr);
3735         addr.sun_family = AF_UNIX;
3736         strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
3737
3738         if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
3739                 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
3740                           strerror(errno)));
3741                 close(fd);
3742                 return map_nt_error_from_unix(errno);
3743         }
3744
3745         status = rpc_transport_sock_init(result, fd, &result->transport);
3746         if (!NT_STATUS_IS_OK(status)) {
3747                 close(fd);
3748                 goto fail;
3749         }
3750
3751         result->transport->transport = NCALRPC;
3752
3753         *presult = result;
3754         return NT_STATUS_OK;
3755
3756  fail:
3757         TALLOC_FREE(result);
3758         return status;
3759 }
3760
3761 struct rpc_pipe_client_np_ref {
3762         struct cli_state *cli;
3763         struct rpc_pipe_client *pipe;
3764 };
3765
3766 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3767 {
3768         DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3769         return 0;
3770 }
3771
3772 /****************************************************************************
3773  Open a named pipe over SMB to a remote server.
3774  *
3775  * CAVEAT CALLER OF THIS FUNCTION:
3776  *    The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3777  *    so be sure that this function is called AFTER any structure (vs pointer)
3778  *    assignment of the cli.  In particular, libsmbclient does structure
3779  *    assignments of cli, which invalidates the data in the returned
3780  *    rpc_pipe_client if this function is called before the structure assignment
3781  *    of cli.
3782  * 
3783  ****************************************************************************/
3784
3785 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3786                                  const struct ndr_syntax_id *abstract_syntax,
3787                                  struct rpc_pipe_client **presult)
3788 {
3789         struct rpc_pipe_client *result;
3790         NTSTATUS status;
3791         struct rpc_pipe_client_np_ref *np_ref;
3792
3793         /* sanity check to protect against crashes */
3794
3795         if ( !cli ) {
3796                 return NT_STATUS_INVALID_HANDLE;
3797         }
3798
3799         result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
3800         if (result == NULL) {
3801                 return NT_STATUS_NO_MEMORY;
3802         }
3803
3804         result->abstract_syntax = *abstract_syntax;
3805         result->transfer_syntax = ndr_transfer_syntax;
3806         result->dispatch = cli_do_rpc_ndr;
3807         result->dispatch_send = cli_do_rpc_ndr_send;
3808         result->dispatch_recv = cli_do_rpc_ndr_recv;
3809         result->desthost = talloc_strdup(result, cli->desthost);
3810         result->srv_name_slash = talloc_asprintf_strupper_m(
3811                 result, "\\\\%s", result->desthost);
3812
3813         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3814         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3815
3816         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3817                 TALLOC_FREE(result);
3818                 return NT_STATUS_NO_MEMORY;
3819         }
3820
3821         status = rpc_transport_np_init(result, cli, abstract_syntax,
3822                                        &result->transport);
3823         if (!NT_STATUS_IS_OK(status)) {
3824                 TALLOC_FREE(result);
3825                 return status;
3826         }
3827
3828         result->transport->transport = NCACN_NP;
3829
3830         np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3831         if (np_ref == NULL) {
3832                 TALLOC_FREE(result);
3833                 return NT_STATUS_NO_MEMORY;
3834         }
3835         np_ref->cli = cli;
3836         np_ref->pipe = result;
3837
3838         DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3839         talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3840
3841         *presult = result;
3842         return NT_STATUS_OK;
3843 }
3844
3845 NTSTATUS rpc_pipe_open_local(TALLOC_CTX *mem_ctx,
3846                              struct rpc_cli_smbd_conn *conn,
3847                              const struct ndr_syntax_id *syntax,
3848                              struct rpc_pipe_client **presult)
3849 {
3850         struct rpc_pipe_client *result;
3851         struct cli_pipe_auth_data *auth;
3852         NTSTATUS status;
3853
3854         result = talloc(mem_ctx, struct rpc_pipe_client);
3855         if (result == NULL) {
3856                 return NT_STATUS_NO_MEMORY;
3857         }
3858         result->abstract_syntax = *syntax;
3859         result->transfer_syntax = ndr_transfer_syntax;
3860         result->dispatch = cli_do_rpc_ndr;
3861         result->dispatch_send = cli_do_rpc_ndr_send;
3862         result->dispatch_recv = cli_do_rpc_ndr_recv;
3863         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3864         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
3865
3866         result->desthost = talloc_strdup(result, global_myname());
3867         result->srv_name_slash = talloc_asprintf_strupper_m(
3868                 result, "\\\\%s", global_myname());
3869         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3870                 TALLOC_FREE(result);
3871                 return NT_STATUS_NO_MEMORY;
3872         }
3873
3874         status = rpc_transport_smbd_init(result, conn, syntax,
3875                                          &result->transport);
3876         if (!NT_STATUS_IS_OK(status)) {
3877                 DEBUG(1, ("rpc_transport_smbd_init failed: %s\n",
3878                           nt_errstr(status)));
3879                 TALLOC_FREE(result);
3880                 return status;
3881         }
3882
3883         status = rpccli_anon_bind_data(result, &auth);
3884         if (!NT_STATUS_IS_OK(status)) {
3885                 DEBUG(1, ("rpccli_anon_bind_data failed: %s\n",
3886                           nt_errstr(status)));
3887                 TALLOC_FREE(result);
3888                 return status;
3889         }
3890
3891         status = rpc_pipe_bind(result, auth);
3892         if (!NT_STATUS_IS_OK(status)) {
3893                 DEBUG(1, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
3894                 TALLOC_FREE(result);
3895                 return status;
3896         }
3897
3898         result->transport->transport = NCACN_INTERNAL;
3899
3900         *presult = result;
3901         return NT_STATUS_OK;
3902 }
3903
3904 /****************************************************************************
3905  Open a pipe to a remote server.
3906  ****************************************************************************/
3907
3908 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3909                                   enum dcerpc_transport_t transport,
3910                                   const struct ndr_syntax_id *interface,
3911                                   struct rpc_pipe_client **presult)
3912 {
3913         switch (transport) {
3914         case NCACN_IP_TCP:
3915                 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
3916                                          presult);
3917         case NCACN_NP:
3918                 return rpc_pipe_open_np(cli, interface, presult);
3919         default:
3920                 return NT_STATUS_NOT_IMPLEMENTED;
3921         }
3922 }
3923
3924 /****************************************************************************
3925  Open a named pipe to an SMB server and bind anonymously.
3926  ****************************************************************************/
3927
3928 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3929                                             enum dcerpc_transport_t transport,
3930                                             const struct ndr_syntax_id *interface,
3931                                             struct rpc_pipe_client **presult)
3932 {
3933         struct rpc_pipe_client *result;
3934         struct cli_pipe_auth_data *auth;
3935         NTSTATUS status;
3936
3937         status = cli_rpc_pipe_open(cli, transport, interface, &result);
3938         if (!NT_STATUS_IS_OK(status)) {
3939                 return status;
3940         }
3941
3942         status = rpccli_anon_bind_data(result, &auth);
3943         if (!NT_STATUS_IS_OK(status)) {
3944                 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3945                           nt_errstr(status)));
3946                 TALLOC_FREE(result);
3947                 return status;
3948         }
3949
3950         /*
3951          * This is a bit of an abstraction violation due to the fact that an
3952          * anonymous bind on an authenticated SMB inherits the user/domain
3953          * from the enclosing SMB creds
3954          */
3955
3956         TALLOC_FREE(auth->user_name);
3957         TALLOC_FREE(auth->domain);
3958
3959         auth->user_name = talloc_strdup(auth, cli->user_name);
3960         auth->domain = talloc_strdup(auth, cli->domain);
3961         auth->user_session_key = data_blob_talloc(auth,
3962                 cli->user_session_key.data,
3963                 cli->user_session_key.length);
3964
3965         if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3966                 TALLOC_FREE(result);
3967                 return NT_STATUS_NO_MEMORY;
3968         }
3969
3970         status = rpc_pipe_bind(result, auth);
3971         if (!NT_STATUS_IS_OK(status)) {
3972                 int lvl = 0;
3973                 if (ndr_syntax_id_equal(interface,
3974                                         &ndr_table_dssetup.syntax_id)) {
3975                         /* non AD domains just don't have this pipe, avoid
3976                          * level 0 statement in that case - gd */
3977                         lvl = 3;
3978                 }
3979                 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3980                             "%s failed with error %s\n",
3981                             get_pipe_name_from_syntax(talloc_tos(), interface),
3982                             nt_errstr(status) ));
3983                 TALLOC_FREE(result);
3984                 return status;
3985         }
3986
3987         DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3988                   "%s and bound anonymously.\n",
3989                   get_pipe_name_from_syntax(talloc_tos(), interface),
3990                   cli->desthost));
3991
3992         *presult = result;
3993         return NT_STATUS_OK;
3994 }
3995
3996 /****************************************************************************
3997  ****************************************************************************/
3998
3999 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
4000                                   const struct ndr_syntax_id *interface,
4001                                   struct rpc_pipe_client **presult)
4002 {
4003         return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
4004                                                   interface, presult);
4005 }
4006
4007 /****************************************************************************
4008  Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
4009  ****************************************************************************/
4010
4011 static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
4012                                                    const struct ndr_syntax_id *interface,
4013                                                    enum dcerpc_transport_t transport,
4014                                                    enum pipe_auth_type auth_type,
4015                                                    enum dcerpc_AuthLevel auth_level,
4016                                                    const char *domain,
4017                                                    const char *username,
4018                                                    const char *password,
4019                                                    struct rpc_pipe_client **presult)
4020 {
4021         struct rpc_pipe_client *result;
4022         struct cli_pipe_auth_data *auth;
4023         NTSTATUS status;
4024
4025         status = cli_rpc_pipe_open(cli, transport, interface, &result);
4026         if (!NT_STATUS_IS_OK(status)) {
4027                 return status;
4028         }
4029
4030         status = rpccli_ntlmssp_bind_data(
4031                 result, auth_type, auth_level, domain, username,
4032                 password, &auth);
4033         if (!NT_STATUS_IS_OK(status)) {
4034                 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
4035                           nt_errstr(status)));
4036                 goto err;
4037         }
4038
4039         status = rpc_pipe_bind(result, auth);
4040         if (!NT_STATUS_IS_OK(status)) {
4041                 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
4042                         nt_errstr(status) ));
4043                 goto err;
4044         }
4045
4046         DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
4047                 "machine %s and bound NTLMSSP as user %s\\%s.\n",
4048                   get_pipe_name_from_syntax(talloc_tos(), interface),
4049                   cli->desthost, domain, username ));
4050
4051         *presult = result;
4052         return NT_STATUS_OK;
4053
4054   err:
4055
4056         TALLOC_FREE(result);
4057         return status;
4058 }
4059
4060 /****************************************************************************
4061  External interface.
4062  Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
4063  ****************************************************************************/
4064
4065 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
4066                                    const struct ndr_syntax_id *interface,
4067                                    enum dcerpc_transport_t transport,
4068                                    enum dcerpc_AuthLevel auth_level,
4069                                    const char *domain,
4070                                    const char *username,
4071                                    const char *password,
4072                                    struct rpc_pipe_client **presult)
4073 {
4074         return cli_rpc_pipe_open_ntlmssp_internal(cli,
4075                                                 interface,
4076                                                 transport,
4077                                                 PIPE_AUTH_TYPE_NTLMSSP,
4078                                                 auth_level,
4079                                                 domain,
4080                                                 username,
4081                                                 password,
4082                                                 presult);
4083 }
4084
4085 /****************************************************************************
4086  External interface.
4087  Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
4088  ****************************************************************************/
4089
4090 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
4091                                           const struct ndr_syntax_id *interface,
4092                                           enum dcerpc_transport_t transport,
4093                                           enum dcerpc_AuthLevel auth_level,
4094                                           const char *domain,
4095                                           const char *username,
4096                                           const char *password,
4097                                           struct rpc_pipe_client **presult)
4098 {
4099         return cli_rpc_pipe_open_ntlmssp_internal(cli,
4100                                                 interface,
4101                                                 transport,
4102                                                 PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
4103                                                 auth_level,
4104                                                 domain,
4105                                                 username,
4106                                                 password,
4107                                                 presult);
4108 }
4109
4110 /****************************************************************************
4111   Get a the schannel session key out of an already opened netlogon pipe.
4112  ****************************************************************************/
4113 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
4114                                                 struct cli_state *cli,
4115                                                 const char *domain,
4116                                                 uint32 *pneg_flags)
4117 {
4118         enum netr_SchannelType sec_chan_type = 0;
4119         unsigned char machine_pwd[16];
4120         const char *machine_account;
4121         NTSTATUS status;
4122
4123         /* Get the machine account credentials from secrets.tdb. */
4124         if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
4125                                &sec_chan_type))
4126         {
4127                 DEBUG(0, ("get_schannel_session_key: could not fetch "
4128                         "trust account password for domain '%s'\n",
4129                         domain));
4130                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
4131         }
4132
4133         status = rpccli_netlogon_setup_creds(netlogon_pipe,
4134                                         cli->desthost, /* server name */
4135                                         domain,        /* domain */
4136                                         global_myname(), /* client name */
4137                                         machine_account, /* machine account name */
4138                                         machine_pwd,
4139                                         sec_chan_type,
4140                                         pneg_flags);
4141
4142         if (!NT_STATUS_IS_OK(status)) {
4143                 DEBUG(3, ("get_schannel_session_key_common: "
4144                           "rpccli_netlogon_setup_creds failed with result %s "
4145                           "to server %s, domain %s, machine account %s.\n",
4146                           nt_errstr(status), cli->desthost, domain,
4147                           machine_account ));
4148                 return status;
4149         }
4150
4151         if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
4152                 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
4153                         cli->desthost));
4154                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4155         }
4156
4157         return NT_STATUS_OK;;
4158 }
4159
4160 /****************************************************************************
4161  Open a netlogon pipe and get the schannel session key.
4162  Now exposed to external callers.
4163  ****************************************************************************/
4164
4165
4166 NTSTATUS get_schannel_session_key(struct cli_state *cli,
4167                                   const char *domain,
4168                                   uint32 *pneg_flags,
4169                                   struct rpc_pipe_client **presult)
4170 {
4171         struct rpc_pipe_client *netlogon_pipe = NULL;
4172         NTSTATUS status;
4173
4174         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
4175                                           &netlogon_pipe);
4176         if (!NT_STATUS_IS_OK(status)) {
4177                 return status;
4178         }
4179
4180         status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
4181                                                  pneg_flags);
4182         if (!NT_STATUS_IS_OK(status)) {
4183                 TALLOC_FREE(netlogon_pipe);
4184                 return status;
4185         }
4186
4187         *presult = netlogon_pipe;
4188         return NT_STATUS_OK;
4189 }
4190
4191 /****************************************************************************
4192  External interface.
4193  Open a named pipe to an SMB server and bind using schannel (bind type 68)
4194  using session_key. sign and seal.
4195
4196  The *pdc will be stolen onto this new pipe
4197  ****************************************************************************/
4198
4199 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
4200                                              const struct ndr_syntax_id *interface,
4201                                              enum dcerpc_transport_t transport,
4202                                              enum dcerpc_AuthLevel auth_level,
4203                                              const char *domain,
4204                                              struct netlogon_creds_CredentialState **pdc,
4205                                              struct rpc_pipe_client **presult)
4206 {
4207         struct rpc_pipe_client *result;
4208         struct cli_pipe_auth_data *auth;
4209         NTSTATUS status;
4210
4211         status = cli_rpc_pipe_open(cli, transport, interface, &result);
4212         if (!NT_STATUS_IS_OK(status)) {
4213                 return status;
4214         }
4215
4216         status = rpccli_schannel_bind_data(result, domain, auth_level,
4217                                            *pdc, &auth);
4218         if (!NT_STATUS_IS_OK(status)) {
4219                 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
4220                           nt_errstr(status)));
4221                 TALLOC_FREE(result);
4222                 return status;
4223         }
4224
4225         status = rpc_pipe_bind(result, auth);
4226         if (!NT_STATUS_IS_OK(status)) {
4227                 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
4228                           "cli_rpc_pipe_bind failed with error %s\n",
4229                           nt_errstr(status) ));
4230                 TALLOC_FREE(result);
4231                 return status;
4232         }
4233
4234         /*
4235          * The credentials on a new netlogon pipe are the ones we are passed
4236          * in - reference them in
4237          */
4238         result->dc = talloc_move(result, pdc);
4239
4240         DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
4241                   "for domain %s and bound using schannel.\n",
4242                   get_pipe_name_from_syntax(talloc_tos(), interface),
4243                   cli->desthost, domain ));
4244
4245         *presult = result;
4246         return NT_STATUS_OK;
4247 }
4248
4249 /****************************************************************************
4250  Open a named pipe to an SMB server and bind using schannel (bind type 68).
4251  Fetch the session key ourselves using a temporary netlogon pipe. This
4252  version uses an ntlmssp auth bound netlogon pipe to get the key.
4253  ****************************************************************************/
4254
4255 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
4256                                                       const char *domain,
4257                                                       const char *username,
4258                                                       const char *password,
4259                                                       uint32 *pneg_flags,
4260                                                       struct rpc_pipe_client **presult)
4261 {
4262         struct rpc_pipe_client *netlogon_pipe = NULL;
4263         NTSTATUS status;
4264
4265         status = cli_rpc_pipe_open_spnego_ntlmssp(
4266                 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
4267                 DCERPC_AUTH_LEVEL_PRIVACY,
4268                 domain, username, password, &netlogon_pipe);
4269         if (!NT_STATUS_IS_OK(status)) {
4270                 return status;
4271         }
4272
4273         status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
4274                                                  pneg_flags);
4275         if (!NT_STATUS_IS_OK(status)) {
4276                 TALLOC_FREE(netlogon_pipe);
4277                 return status;
4278         }
4279
4280         *presult = netlogon_pipe;
4281         return NT_STATUS_OK;
4282 }
4283
4284 /****************************************************************************
4285  Open a named pipe to an SMB server and bind using schannel (bind type 68).
4286  Fetch the session key ourselves using a temporary netlogon pipe. This version
4287  uses an ntlmssp bind to get the session key.
4288  ****************************************************************************/
4289
4290 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
4291                                                  const struct ndr_syntax_id *interface,
4292                                                  enum dcerpc_transport_t transport,
4293                                                  enum dcerpc_AuthLevel auth_level,
4294                                                  const char *domain,
4295                                                  const char *username,
4296                                                  const char *password,
4297                                                  struct rpc_pipe_client **presult)
4298 {
4299         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4300         struct rpc_pipe_client *netlogon_pipe = NULL;
4301         struct rpc_pipe_client *result = NULL;
4302         NTSTATUS status;
4303
4304         status = get_schannel_session_key_auth_ntlmssp(
4305                 cli, domain, username, password, &neg_flags, &netlogon_pipe);
4306         if (!NT_STATUS_IS_OK(status)) {
4307                 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
4308                         "key from server %s for domain %s.\n",
4309                         cli->desthost, domain ));
4310                 return status;
4311         }
4312
4313         status = cli_rpc_pipe_open_schannel_with_key(
4314                 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4315                 &result);
4316
4317         /* Now we've bound using the session key we can close the netlog pipe. */
4318         TALLOC_FREE(netlogon_pipe);
4319
4320         if (NT_STATUS_IS_OK(status)) {
4321                 *presult = result;
4322         }
4323         return status;
4324 }
4325
4326 /****************************************************************************
4327  Open a named pipe to an SMB server and bind using schannel (bind type 68).
4328  Fetch the session key ourselves using a temporary netlogon pipe.
4329  ****************************************************************************/
4330
4331 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
4332                                     const struct ndr_syntax_id *interface,
4333                                     enum dcerpc_transport_t transport,
4334                                     enum dcerpc_AuthLevel auth_level,
4335                                     const char *domain,
4336                                     struct rpc_pipe_client **presult)
4337 {
4338         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
4339         struct rpc_pipe_client *netlogon_pipe = NULL;
4340         struct rpc_pipe_client *result = NULL;
4341         NTSTATUS status;
4342
4343         status = get_schannel_session_key(cli, domain, &neg_flags,
4344                                           &netlogon_pipe);
4345         if (!NT_STATUS_IS_OK(status)) {
4346                 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
4347                         "key from server %s for domain %s.\n",
4348                         cli->desthost, domain ));
4349                 return status;
4350         }
4351
4352         status = cli_rpc_pipe_open_schannel_with_key(
4353                 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
4354                 &result);
4355
4356         /* Now we've bound using the session key we can close the netlog pipe. */
4357         TALLOC_FREE(netlogon_pipe);
4358
4359         if (NT_STATUS_IS_OK(status)) {
4360                 *presult = result;
4361         }
4362
4363         return status;
4364 }
4365
4366 /****************************************************************************
4367  Open a named pipe to an SMB server and bind using krb5 (bind type 16).
4368  The idea is this can be called with service_princ, username and password all
4369  NULL so long as the caller has a TGT.
4370  ****************************************************************************/
4371
4372 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
4373                                 const struct ndr_syntax_id *interface,
4374                                 enum dcerpc_AuthLevel auth_level,
4375                                 const char *service_princ,
4376                                 const char *username,
4377                                 const char *password,
4378                                 struct rpc_pipe_client **presult)
4379 {
4380 #ifdef HAVE_KRB5
4381         struct rpc_pipe_client *result;
4382         struct cli_pipe_auth_data *auth;
4383         NTSTATUS status;
4384
4385         status = cli_rpc_pipe_open(cli, NCACN_NP, interface, &result);
4386         if (!NT_STATUS_IS_OK(status)) {
4387                 return status;
4388         }
4389
4390         status = rpccli_kerberos_bind_data(result, auth_level, service_princ,
4391                                            username, password, &auth);
4392         if (!NT_STATUS_IS_OK(status)) {
4393                 DEBUG(0, ("rpccli_kerberos_bind_data returned %s\n",
4394                           nt_errstr(status)));
4395                 TALLOC_FREE(result);
4396                 return status;
4397         }
4398
4399         status = rpc_pipe_bind(result, auth);
4400         if (!NT_STATUS_IS_OK(status)) {
4401                 DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed "
4402                           "with error %s\n", nt_errstr(status)));
4403                 TALLOC_FREE(result);
4404                 return status;
4405         }
4406
4407         *presult = result;
4408         return NT_STATUS_OK;
4409 #else
4410         DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
4411         return NT_STATUS_NOT_IMPLEMENTED;
4412 #endif
4413 }
4414
4415 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
4416                              struct rpc_pipe_client *cli,
4417                              DATA_BLOB *session_key)
4418 {
4419         if (!session_key || !cli) {
4420                 return NT_STATUS_INVALID_PARAMETER;
4421         }
4422
4423         if (!cli->auth) {
4424                 return NT_STATUS_INVALID_PARAMETER;
4425         }
4426
4427         switch (cli->auth->auth_type) {
4428                 case PIPE_AUTH_TYPE_SCHANNEL:
4429                         *session_key = data_blob_talloc(mem_ctx,
4430                                 cli->auth->a_u.schannel_auth->creds->session_key, 16);
4431                         break;
4432                 case PIPE_AUTH_TYPE_NTLMSSP:
4433                 case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
4434                         *session_key = data_blob_talloc(mem_ctx,
4435                                 cli->auth->a_u.ntlmssp_state->session_key.data,
4436                                 cli->auth->a_u.ntlmssp_state->session_key.length);
4437                         break;
4438                 case PIPE_AUTH_TYPE_KRB5:
4439                 case PIPE_AUTH_TYPE_SPNEGO_KRB5:
4440                         *session_key = data_blob_talloc(mem_ctx,
4441                                 cli->auth->a_u.kerberos_auth->session_key.data,
4442                                 cli->auth->a_u.kerberos_auth->session_key.length);
4443                         break;
4444                 case PIPE_AUTH_TYPE_NONE:
4445                         *session_key = data_blob_talloc(mem_ctx,
4446                                 cli->auth->user_session_key.data,
4447                                 cli->auth->user_session_key.length);
4448                         break;
4449                 default:
4450                         return NT_STATUS_NO_USER_SESSION_KEY;
4451         }
4452
4453         return NT_STATUS_OK;
4454 }