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