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