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