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