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