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