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