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