Revert "HACK: s3:rpc_client: multiple dcerpc_presentations, only one wins."
[metze/samba/wip.git] / source3 / rpc_client / cli_pipe.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client routines
4  *  Largely rewritten by Jeremy Allison             2005.
5  *  Heavily modified by Simo Sorce                  2010.
6  *  Copyright Andrew Bartlett                       2011.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23 #include "../lib/util/tevent_ntstatus.h"
24 #include "librpc/gen_ndr/ndr_epmapper_c.h"
25 #include "../librpc/gen_ndr/ndr_dssetup.h"
26 #include "../libcli/auth/schannel.h"
27 #include "../libcli/auth/netlogon_creds_cli.h"
28 #include "auth_generic.h"
29 #include "librpc/gen_ndr/ndr_dcerpc.h"
30 #include "librpc/gen_ndr/ndr_netlogon_c.h"
31 #include "librpc/rpc/dcerpc.h"
32 #include "rpc_dce.h"
33 #include "cli_pipe.h"
34 #include "libsmb/libsmb.h"
35 #include "auth/gensec/gensec.h"
36 #include "auth/credentials/credentials.h"
37 #include "../libcli/smb/smbXcli_base.h"
38 #include "../libcli/smb/tstream_smbXcli_np.h"
39 #include "librpc/rpc/dcerpc_connection.h"
40
41 #undef DBGC_CLASS
42 #define DBGC_CLASS DBGC_RPC_CLI
43
44 /********************************************************************
45  Pipe description for a DEBUG
46  ********************************************************************/
47 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
48                                    struct rpc_pipe_client *cli)
49 {
50         char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
51         if (result == NULL) {
52                 return "pipe";
53         }
54         return result;
55 }
56
57 /********************************************************************
58  Rpc pipe call id.
59  ********************************************************************/
60
61 static uint32 get_rpc_call_id(void)
62 {
63         static uint32 call_id = 0;
64         return ++call_id;
65 }
66
67 /*******************************************************************
68  Use SMBreadX to get rest of one fragment's worth of rpc data.
69  Reads the whole size or give an error message
70  ********************************************************************/
71
72 struct rpc_read_state {
73         struct tevent_context *ev;
74         struct rpc_cli_transport *transport;
75         uint8_t *data;
76         size_t size;
77         size_t num_read;
78 };
79
80 static void rpc_read_done(struct tevent_req *subreq);
81
82 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
83                                         struct tevent_context *ev,
84                                         struct rpc_cli_transport *transport,
85                                         uint8_t *data, size_t size)
86 {
87         struct tevent_req *req, *subreq;
88         struct rpc_read_state *state;
89
90         req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
91         if (req == NULL) {
92                 return NULL;
93         }
94         state->ev = ev;
95         state->transport = transport;
96         state->data = data;
97         state->size = size;
98         state->num_read = 0;
99
100         DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
101
102         subreq = transport->read_send(state, ev, (uint8_t *)data, size,
103                                       transport->priv);
104         if (subreq == NULL) {
105                 goto fail;
106         }
107         tevent_req_set_callback(subreq, rpc_read_done, req);
108         return req;
109
110  fail:
111         TALLOC_FREE(req);
112         return NULL;
113 }
114
115 static void rpc_read_done(struct tevent_req *subreq)
116 {
117         struct tevent_req *req = tevent_req_callback_data(
118                 subreq, struct tevent_req);
119         struct rpc_read_state *state = tevent_req_data(
120                 req, struct rpc_read_state);
121         NTSTATUS status;
122         ssize_t received;
123
124         status = state->transport->read_recv(subreq, &received);
125         TALLOC_FREE(subreq);
126         if (!NT_STATUS_IS_OK(status)) {
127                 tevent_req_nterror(req, status);
128                 return;
129         }
130
131         state->num_read += received;
132         if (state->num_read == state->size) {
133                 tevent_req_done(req);
134                 return;
135         }
136
137         subreq = state->transport->read_send(state, state->ev,
138                                              state->data + state->num_read,
139                                              state->size - state->num_read,
140                                              state->transport->priv);
141         if (tevent_req_nomem(subreq, req)) {
142                 return;
143         }
144         tevent_req_set_callback(subreq, rpc_read_done, req);
145 }
146
147 static NTSTATUS rpc_read_recv(struct tevent_req *req)
148 {
149         return tevent_req_simple_recv_ntstatus(req);
150 }
151
152 struct rpc_write_state {
153         struct tevent_context *ev;
154         struct rpc_cli_transport *transport;
155         const uint8_t *data;
156         size_t size;
157         size_t num_written;
158 };
159
160 static void rpc_write_done(struct tevent_req *subreq);
161
162 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
163                                          struct tevent_context *ev,
164                                          struct rpc_cli_transport *transport,
165                                          const uint8_t *data, size_t size)
166 {
167         struct tevent_req *req, *subreq;
168         struct rpc_write_state *state;
169
170         req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
171         if (req == NULL) {
172                 return NULL;
173         }
174         state->ev = ev;
175         state->transport = transport;
176         state->data = data;
177         state->size = size;
178         state->num_written = 0;
179
180         DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
181
182         subreq = transport->write_send(state, ev, data, size, transport->priv);
183         if (subreq == NULL) {
184                 goto fail;
185         }
186         tevent_req_set_callback(subreq, rpc_write_done, req);
187         return req;
188  fail:
189         TALLOC_FREE(req);
190         return NULL;
191 }
192
193 static void rpc_write_done(struct tevent_req *subreq)
194 {
195         struct tevent_req *req = tevent_req_callback_data(
196                 subreq, struct tevent_req);
197         struct rpc_write_state *state = tevent_req_data(
198                 req, struct rpc_write_state);
199         NTSTATUS status;
200         ssize_t written;
201
202         status = state->transport->write_recv(subreq, &written);
203         TALLOC_FREE(subreq);
204         if (!NT_STATUS_IS_OK(status)) {
205                 tevent_req_nterror(req, status);
206                 return;
207         }
208
209         state->num_written += written;
210
211         if (state->num_written == state->size) {
212                 tevent_req_done(req);
213                 return;
214         }
215
216         subreq = state->transport->write_send(state, state->ev,
217                                               state->data + state->num_written,
218                                               state->size - state->num_written,
219                                               state->transport->priv);
220         if (tevent_req_nomem(subreq, req)) {
221                 return;
222         }
223         tevent_req_set_callback(subreq, rpc_write_done, req);
224 }
225
226 static NTSTATUS rpc_write_recv(struct tevent_req *req)
227 {
228         return tevent_req_simple_recv_ntstatus(req);
229 }
230
231
232 /****************************************************************************
233  Try and get a PDU's worth of data from current_pdu. If not, then read more
234  from the wire.
235  ****************************************************************************/
236
237 struct get_complete_frag_state {
238         struct tevent_context *ev;
239         struct rpc_pipe_client *cli;
240         uint16_t frag_len;
241         DATA_BLOB *pdu;
242 };
243
244 static void get_complete_frag_got_header(struct tevent_req *subreq);
245 static void get_complete_frag_got_rest(struct tevent_req *subreq);
246
247 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
248                                                  struct tevent_context *ev,
249                                                  struct rpc_pipe_client *cli,
250                                                  DATA_BLOB *pdu)
251 {
252         struct tevent_req *req, *subreq;
253         struct get_complete_frag_state *state;
254         size_t received;
255         NTSTATUS status;
256
257         req = tevent_req_create(mem_ctx, &state,
258                                 struct get_complete_frag_state);
259         if (req == NULL) {
260                 return NULL;
261         }
262         state->ev = ev;
263         state->cli = cli;
264         state->frag_len = RPC_HEADER_LEN;
265         state->pdu = pdu;
266
267         received = pdu->length;
268         if (received < RPC_HEADER_LEN) {
269                 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
270                         status = NT_STATUS_NO_MEMORY;
271                         goto post_status;
272                 }
273                 subreq = rpc_read_send(state, state->ev,
274                                         state->cli->transport,
275                                         pdu->data + received,
276                                         RPC_HEADER_LEN - received);
277                 if (subreq == NULL) {
278                         status = NT_STATUS_NO_MEMORY;
279                         goto post_status;
280                 }
281                 tevent_req_set_callback(subreq, get_complete_frag_got_header,
282                                         req);
283                 return req;
284         }
285
286         state->frag_len = dcerpc_get_frag_length(pdu);
287         if (state->frag_len < RPC_HEADER_LEN) {
288                 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
289                 return tevent_req_post(req, ev);
290         }
291
292         /*
293          * Ensure we have frag_len bytes of data.
294          */
295         if (received < state->frag_len) {
296                 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
297                         status = NT_STATUS_NO_MEMORY;
298                         goto post_status;
299                 }
300                 subreq = rpc_read_send(state, state->ev,
301                                         state->cli->transport,
302                                         pdu->data + received,
303                                         state->frag_len - received);
304                 if (subreq == NULL) {
305                         status = NT_STATUS_NO_MEMORY;
306                         goto post_status;
307                 }
308                 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
309                                         req);
310                 return req;
311         }
312
313         status = NT_STATUS_OK;
314  post_status:
315         if (NT_STATUS_IS_OK(status)) {
316                 tevent_req_done(req);
317         } else {
318                 tevent_req_nterror(req, status);
319         }
320         return tevent_req_post(req, ev);
321 }
322
323 static void get_complete_frag_got_header(struct tevent_req *subreq)
324 {
325         struct tevent_req *req = tevent_req_callback_data(
326                 subreq, struct tevent_req);
327         struct get_complete_frag_state *state = tevent_req_data(
328                 req, struct get_complete_frag_state);
329         NTSTATUS status;
330
331         status = rpc_read_recv(subreq);
332         TALLOC_FREE(subreq);
333         if (!NT_STATUS_IS_OK(status)) {
334                 tevent_req_nterror(req, status);
335                 return;
336         }
337
338         state->frag_len = dcerpc_get_frag_length(state->pdu);
339         if (state->frag_len < RPC_HEADER_LEN) {
340                 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
341                 return;
342         }
343
344         if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
345                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
346                 return;
347         }
348
349         /*
350          * We're here in this piece of code because we've read exactly
351          * RPC_HEADER_LEN bytes into state->pdu.
352          */
353
354         subreq = rpc_read_send(state, state->ev, state->cli->transport,
355                                 state->pdu->data + RPC_HEADER_LEN,
356                                 state->frag_len - RPC_HEADER_LEN);
357         if (tevent_req_nomem(subreq, req)) {
358                 return;
359         }
360         tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
361 }
362
363 static void get_complete_frag_got_rest(struct tevent_req *subreq)
364 {
365         struct tevent_req *req = tevent_req_callback_data(
366                 subreq, struct tevent_req);
367         NTSTATUS status;
368
369         status = rpc_read_recv(subreq);
370         TALLOC_FREE(subreq);
371         if (!NT_STATUS_IS_OK(status)) {
372                 tevent_req_nterror(req, status);
373                 return;
374         }
375         tevent_req_done(req);
376 }
377
378 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
379 {
380         return tevent_req_simple_recv_ntstatus(req);
381 }
382
383 /****************************************************************************
384  Do basic authentication checks on an incoming pdu.
385  ****************************************************************************/
386
387 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
388                                                 struct rpc_pipe_client *cli,
389                                                 struct ncacn_packet *pkt,
390                                                 DATA_BLOB *pdu,
391                                                 uint8_t expected_pkt_type,
392                                                 uint32_t call_id,
393                                                 DATA_BLOB *rdata,
394                                                 DATA_BLOB *reply_pdu)
395 {
396         struct dcerpc_response *r;
397         NTSTATUS ret = NT_STATUS_OK;
398         size_t pad_len = 0;
399
400         /*
401          * Point the return values at the real data including the RPC
402          * header. Just in case the caller wants it.
403          */
404         *rdata = *pdu;
405
406         /* Ensure we have the correct type. */
407         switch (pkt->ptype) {
408         case DCERPC_PKT_ALTER_RESP:
409         case DCERPC_PKT_BIND_ACK:
410
411                 /* Client code never receives this kind of packets */
412                 break;
413
414
415         case DCERPC_PKT_RESPONSE:
416
417                 r = &pkt->u.response;
418
419                 /* Here's where we deal with incoming sign/seal. */
420                 ret = dcerpc_check_auth(cli->auth, pkt,
421                                         &r->stub_and_verifier,
422                                         DCERPC_RESPONSE_LENGTH,
423                                         pdu, &pad_len);
424                 if (!NT_STATUS_IS_OK(ret)) {
425                         return ret;
426                 }
427
428                 if (pkt->frag_length < DCERPC_RESPONSE_LENGTH + pad_len) {
429                         return NT_STATUS_BUFFER_TOO_SMALL;
430                 }
431
432                 /* Point the return values at the NDR data. */
433                 rdata->data = r->stub_and_verifier.data;
434
435                 if (pkt->auth_length) {
436                         /* We've already done integer wrap tests in
437                          * dcerpc_check_auth(). */
438                         rdata->length = r->stub_and_verifier.length
439                                          - pad_len
440                                          - DCERPC_AUTH_TRAILER_LENGTH
441                                          - pkt->auth_length;
442                 } else {
443                         rdata->length = r->stub_and_verifier.length;
444                 }
445
446                 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
447                            (long unsigned int)pdu->length,
448                            (long unsigned int)rdata->length,
449                            (unsigned int)pad_len));
450
451                 /*
452                  * If this is the first reply, and the allocation hint is
453                  * reasonable, try and set up the reply_pdu DATA_BLOB to the
454                  * correct size.
455                  */
456
457                 if ((reply_pdu->length == 0) &&
458                     r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
459                         if (!data_blob_realloc(mem_ctx, reply_pdu,
460                                                         r->alloc_hint)) {
461                                 DEBUG(0, ("reply alloc hint %d too "
462                                           "large to allocate\n",
463                                           (int)r->alloc_hint));
464                                 return NT_STATUS_NO_MEMORY;
465                         }
466                 }
467
468                 break;
469
470         case DCERPC_PKT_BIND_NAK:
471                 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
472                           rpccli_pipe_txt(talloc_tos(), cli)));
473                 /* Use this for now... */
474                 return NT_STATUS_NETWORK_ACCESS_DENIED;
475
476         case DCERPC_PKT_FAULT:
477
478                 DEBUG(1, (__location__ ": RPC fault code %s received "
479                           "from %s!\n",
480                           dcerpc_errstr(talloc_tos(),
481                           pkt->u.fault.status),
482                           rpccli_pipe_txt(talloc_tos(), cli)));
483
484                 return dcerpc_fault_to_nt_status(pkt->u.fault.status);
485
486         default:
487                 DEBUG(0, (__location__ "Unknown packet type %u received "
488                           "from %s!\n",
489                           (unsigned int)pkt->ptype,
490                           rpccli_pipe_txt(talloc_tos(), cli)));
491                 return NT_STATUS_RPC_PROTOCOL_ERROR;
492         }
493
494         if (pkt->ptype != expected_pkt_type) {
495                 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
496                           "RPC packet type - %u, not %u\n",
497                           rpccli_pipe_txt(talloc_tos(), cli),
498                           pkt->ptype, expected_pkt_type));
499                 return NT_STATUS_RPC_PROTOCOL_ERROR;
500         }
501
502         if (pkt->call_id != call_id) {
503                 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
504                           "RPC call_id - %u, not %u\n",
505                           rpccli_pipe_txt(talloc_tos(), cli),
506                           pkt->call_id, call_id));
507                 return NT_STATUS_RPC_PROTOCOL_ERROR;
508         }
509
510         /* Do this just before return - we don't want to modify any rpc header
511            data before now as we may have needed to do cryptographic actions on
512            it before. */
513
514         if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
515             !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
516                 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
517                           "fragment first/last ON.\n"));
518                 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
519         }
520
521         return NT_STATUS_OK;
522 }
523
524 /****************************************************************************
525  Call a remote api on an arbitrary pipe.  takes param, data and setup buffers.
526 ****************************************************************************/
527
528 struct cli_api_pipe_state {
529         struct tevent_context *ev;
530         struct rpc_cli_transport *transport;
531         uint8_t *rdata;
532         uint32_t rdata_len;
533 };
534
535 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
536 static void cli_api_pipe_write_done(struct tevent_req *subreq);
537 static void cli_api_pipe_read_done(struct tevent_req *subreq);
538
539 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
540                                             struct tevent_context *ev,
541                                             struct rpc_cli_transport *transport,
542                                             uint8_t *data, size_t data_len,
543                                             uint32_t max_rdata_len)
544 {
545         struct tevent_req *req, *subreq;
546         struct cli_api_pipe_state *state;
547         NTSTATUS status;
548
549         req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
550         if (req == NULL) {
551                 return NULL;
552         }
553         state->ev = ev;
554         state->transport = transport;
555
556         if (max_rdata_len < RPC_HEADER_LEN) {
557                 /*
558                  * For a RPC reply we always need at least RPC_HEADER_LEN
559                  * bytes. We check this here because we will receive
560                  * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
561                  */
562                 status = NT_STATUS_INVALID_PARAMETER;
563                 goto post_status;
564         }
565
566         if (transport->trans_send != NULL) {
567                 subreq = transport->trans_send(state, ev, data, data_len,
568                                                max_rdata_len, transport->priv);
569                 if (subreq == NULL) {
570                         goto fail;
571                 }
572                 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
573                 return req;
574         }
575
576         /*
577          * If the transport does not provide a "trans" routine, i.e. for
578          * example the ncacn_ip_tcp transport, do the write/read step here.
579          */
580
581         subreq = rpc_write_send(state, ev, transport, data, data_len);
582         if (subreq == NULL) {
583                 goto fail;
584         }
585         tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
586         return req;
587
588  post_status:
589         tevent_req_nterror(req, status);
590         return tevent_req_post(req, ev);
591  fail:
592         TALLOC_FREE(req);
593         return NULL;
594 }
595
596 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
597 {
598         struct tevent_req *req = tevent_req_callback_data(
599                 subreq, struct tevent_req);
600         struct cli_api_pipe_state *state = tevent_req_data(
601                 req, struct cli_api_pipe_state);
602         NTSTATUS status;
603
604         status = state->transport->trans_recv(subreq, state, &state->rdata,
605                                               &state->rdata_len);
606         TALLOC_FREE(subreq);
607         if (!NT_STATUS_IS_OK(status)) {
608                 tevent_req_nterror(req, status);
609                 return;
610         }
611         tevent_req_done(req);
612 }
613
614 static void cli_api_pipe_write_done(struct tevent_req *subreq)
615 {
616         struct tevent_req *req = tevent_req_callback_data(
617                 subreq, struct tevent_req);
618         struct cli_api_pipe_state *state = tevent_req_data(
619                 req, struct cli_api_pipe_state);
620         NTSTATUS status;
621
622         status = rpc_write_recv(subreq);
623         TALLOC_FREE(subreq);
624         if (!NT_STATUS_IS_OK(status)) {
625                 tevent_req_nterror(req, status);
626                 return;
627         }
628
629         state->rdata = talloc_array(state, uint8_t, RPC_HEADER_LEN);
630         if (tevent_req_nomem(state->rdata, req)) {
631                 return;
632         }
633
634         /*
635          * We don't need to use rpc_read_send here, the upper layer will cope
636          * with a short read, transport->trans_send could also return less
637          * than state->max_rdata_len.
638          */
639         subreq = state->transport->read_send(state, state->ev, state->rdata,
640                                              RPC_HEADER_LEN,
641                                              state->transport->priv);
642         if (tevent_req_nomem(subreq, req)) {
643                 return;
644         }
645         tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
646 }
647
648 static void cli_api_pipe_read_done(struct tevent_req *subreq)
649 {
650         struct tevent_req *req = tevent_req_callback_data(
651                 subreq, struct tevent_req);
652         struct cli_api_pipe_state *state = tevent_req_data(
653                 req, struct cli_api_pipe_state);
654         NTSTATUS status;
655         ssize_t received;
656
657         status = state->transport->read_recv(subreq, &received);
658         TALLOC_FREE(subreq);
659         if (!NT_STATUS_IS_OK(status)) {
660                 tevent_req_nterror(req, status);
661                 return;
662         }
663         state->rdata_len = received;
664         tevent_req_done(req);
665 }
666
667 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
668                                   uint8_t **prdata, uint32_t *prdata_len)
669 {
670         struct cli_api_pipe_state *state = tevent_req_data(
671                 req, struct cli_api_pipe_state);
672         NTSTATUS status;
673
674         if (tevent_req_is_nterror(req, &status)) {
675                 return status;
676         }
677
678         *prdata = talloc_move(mem_ctx, &state->rdata);
679         *prdata_len = state->rdata_len;
680         return NT_STATUS_OK;
681 }
682
683 /****************************************************************************
684  Send data on an rpc pipe via trans. The data must be the last
685  pdu fragment of an NDR data stream.
686
687  Receive response data from an rpc pipe, which may be large...
688
689  Read the first fragment: unfortunately have to use SMBtrans for the first
690  bit, then SMBreadX for subsequent bits.
691
692  If first fragment received also wasn't the last fragment, continue
693  getting fragments until we _do_ receive the last fragment.
694
695  Request/Response PDU's look like the following...
696
697  |<------------------PDU len----------------------------------------------->|
698  |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
699
700  +------------+-----------------+-------------+---------------+-------------+
701  | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR      | AUTH DATA   |
702  +------------+-----------------+-------------+---------------+-------------+
703
704  Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
705  signing & sealing being negotiated.
706
707  ****************************************************************************/
708
709 struct rpc_api_pipe_state {
710         struct tevent_context *ev;
711         struct rpc_pipe_client *cli;
712         uint8_t expected_pkt_type;
713         uint32_t call_id;
714
715         DATA_BLOB incoming_frag;
716         struct ncacn_packet *pkt;
717
718         /* Incoming reply */
719         DATA_BLOB reply_pdu;
720         size_t reply_pdu_offset;
721         uint8_t endianess;
722 };
723
724 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
725 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
726 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq);
727
728 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
729                                             struct tevent_context *ev,
730                                             struct rpc_pipe_client *cli,
731                                             DATA_BLOB *data, /* Outgoing PDU */
732                                             uint8_t expected_pkt_type,
733                                             uint32_t call_id)
734 {
735         struct tevent_req *req, *subreq;
736         struct rpc_api_pipe_state *state;
737         uint16_t max_recv_frag;
738         NTSTATUS status;
739
740         req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
741         if (req == NULL) {
742                 return NULL;
743         }
744         state->ev = ev;
745         state->cli = cli;
746         state->expected_pkt_type = expected_pkt_type;
747         state->call_id = call_id;
748         state->endianess = DCERPC_DREP_LE;
749
750         /*
751          * Ensure we're not sending too much.
752          */
753         if (data->length > cli->max_xmit_frag) {
754                 status = NT_STATUS_INVALID_PARAMETER;
755                 goto post_status;
756         }
757
758         DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
759
760         if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
761                 subreq = rpc_write_send(state, ev, cli->transport,
762                                         data->data, data->length);
763                 if (subreq == NULL) {
764                         goto fail;
765                 }
766                 tevent_req_set_callback(subreq, rpc_api_pipe_auth3_done, req);
767                 return req;
768         }
769
770         /* get the header first, then fetch the rest once we have
771          * the frag_length available */
772         max_recv_frag = RPC_HEADER_LEN;
773
774         subreq = cli_api_pipe_send(state, ev, cli->transport,
775                                    data->data, data->length, max_recv_frag);
776         if (subreq == NULL) {
777                 goto fail;
778         }
779         tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
780         return req;
781
782  post_status:
783         tevent_req_nterror(req, status);
784         return tevent_req_post(req, ev);
785  fail:
786         TALLOC_FREE(req);
787         return NULL;
788 }
789
790 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq)
791 {
792         struct tevent_req *req =
793                 tevent_req_callback_data(subreq,
794                 struct tevent_req);
795         NTSTATUS status;
796
797         status = rpc_write_recv(subreq);
798         TALLOC_FREE(subreq);
799         if (!NT_STATUS_IS_OK(status)) {
800                 tevent_req_nterror(req, status);
801                 return;
802         }
803
804         tevent_req_done(req);
805 }
806
807 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
808 {
809         struct tevent_req *req = tevent_req_callback_data(
810                 subreq, struct tevent_req);
811         struct rpc_api_pipe_state *state = tevent_req_data(
812                 req, struct rpc_api_pipe_state);
813         NTSTATUS status;
814         uint8_t *rdata = NULL;
815         uint32_t rdata_len = 0;
816
817         status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
818         TALLOC_FREE(subreq);
819         if (!NT_STATUS_IS_OK(status)) {
820                 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
821                 tevent_req_nterror(req, status);
822                 return;
823         }
824
825         if (rdata == NULL) {
826                 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
827                          rpccli_pipe_txt(talloc_tos(), state->cli)));
828                 tevent_req_done(req);
829                 return;
830         }
831
832         /*
833          * Move data on state->incoming_frag.
834          */
835         state->incoming_frag.data = talloc_move(state, &rdata);
836         state->incoming_frag.length = rdata_len;
837         if (!state->incoming_frag.data) {
838                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
839                 return;
840         }
841
842         /* Ensure we have enough data for a pdu. */
843         subreq = get_complete_frag_send(state, state->ev, state->cli,
844                                         &state->incoming_frag);
845         if (tevent_req_nomem(subreq, req)) {
846                 return;
847         }
848         tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
849 }
850
851 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
852 {
853         struct tevent_req *req = tevent_req_callback_data(
854                 subreq, struct tevent_req);
855         struct rpc_api_pipe_state *state = tevent_req_data(
856                 req, struct rpc_api_pipe_state);
857         NTSTATUS status;
858         DATA_BLOB rdata = data_blob_null;
859
860         status = get_complete_frag_recv(subreq);
861         TALLOC_FREE(subreq);
862         if (!NT_STATUS_IS_OK(status)) {
863                 DEBUG(5, ("get_complete_frag failed: %s\n",
864                           nt_errstr(status)));
865                 tevent_req_nterror(req, status);
866                 return;
867         }
868
869         state->pkt = talloc(state, struct ncacn_packet);
870         if (!state->pkt) {
871                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
872                 return;
873         }
874
875         status = dcerpc_pull_ncacn_packet(state->pkt,
876                                           &state->incoming_frag,
877                                           state->pkt,
878                                           !state->endianess);
879         if (!NT_STATUS_IS_OK(status)) {
880                 tevent_req_nterror(req, status);
881                 return;
882         }
883
884         if (state->incoming_frag.length != state->pkt->frag_length) {
885                 DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
886                           (unsigned int)state->incoming_frag.length,
887                           (unsigned int)state->pkt->frag_length));
888                 tevent_req_nterror(req,  NT_STATUS_INVALID_PARAMETER);
889                 return;
890         }
891
892         status = cli_pipe_validate_current_pdu(state,
893                                                 state->cli, state->pkt,
894                                                 &state->incoming_frag,
895                                                 state->expected_pkt_type,
896                                                 state->call_id,
897                                                 &rdata,
898                                                 &state->reply_pdu);
899
900         DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
901                   (unsigned)state->incoming_frag.length,
902                   (unsigned)state->reply_pdu_offset,
903                   nt_errstr(status)));
904
905         if (!NT_STATUS_IS_OK(status)) {
906                 tevent_req_nterror(req, status);
907                 return;
908         }
909
910         if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
911             && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
912                 /*
913                  * Set the data type correctly for big-endian data on the
914                  * first packet.
915                  */
916                 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
917                           "big-endian.\n",
918                           rpccli_pipe_txt(talloc_tos(), state->cli)));
919                 state->endianess = 0x00; /* BIG ENDIAN */
920         }
921         /*
922          * Check endianness on subsequent packets.
923          */
924         if (state->endianess != state->pkt->drep[0]) {
925                 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
926                          "%s\n",
927                          state->endianess?"little":"big",
928                          state->pkt->drep[0]?"little":"big"));
929                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
930                 return;
931         }
932
933         /* Now copy the data portion out of the pdu into rbuf. */
934         if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
935                 if (!data_blob_realloc(NULL, &state->reply_pdu,
936                                 state->reply_pdu_offset + rdata.length)) {
937                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
938                         return;
939                 }
940         }
941
942         memcpy(state->reply_pdu.data + state->reply_pdu_offset,
943                 rdata.data, rdata.length);
944         state->reply_pdu_offset += rdata.length;
945
946         /* reset state->incoming_frag, there is no need to free it,
947          * it will be reallocated to the right size the next time
948          * it is used */
949         state->incoming_frag.length = 0;
950
951         if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
952                 /* make sure the pdu length is right now that we
953                  * have all the data available (alloc hint may
954                  * have allocated more than was actually used) */
955                 state->reply_pdu.length = state->reply_pdu_offset;
956                 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
957                           rpccli_pipe_txt(talloc_tos(), state->cli),
958                           (unsigned)state->reply_pdu.length));
959                 tevent_req_done(req);
960                 return;
961         }
962
963         subreq = get_complete_frag_send(state, state->ev, state->cli,
964                                         &state->incoming_frag);
965         if (tevent_req_nomem(subreq, req)) {
966                 return;
967         }
968         tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
969 }
970
971 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
972                                   struct ncacn_packet **pkt,
973                                   DATA_BLOB *reply_pdu)
974 {
975         struct rpc_api_pipe_state *state = tevent_req_data(
976                 req, struct rpc_api_pipe_state);
977         NTSTATUS status;
978
979         if (tevent_req_is_nterror(req, &status)) {
980                 return status;
981         }
982
983         /* return data to caller and assign it ownership of memory */
984         if (reply_pdu) {
985                 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
986                 reply_pdu->length = state->reply_pdu.length;
987                 state->reply_pdu.length = 0;
988         } else {
989                 data_blob_free(&state->reply_pdu);
990         }
991
992         if (pkt) {
993                 *pkt = talloc_steal(mem_ctx, state->pkt);
994         }
995
996         return NT_STATUS_OK;
997 }
998
999 /*******************************************************************
1000  Creates NTLMSSP auth bind.
1001  ********************************************************************/
1002
1003 static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1004                                                  TALLOC_CTX *mem_ctx,
1005                                                  DATA_BLOB *auth_token,
1006                                                  bool *client_hdr_signing)
1007 {
1008         struct gensec_security *gensec_security;
1009         DATA_BLOB null_blob = data_blob_null;
1010         NTSTATUS status;
1011
1012         gensec_security = talloc_get_type_abort(cli->auth->auth_ctx,
1013                                         struct gensec_security);
1014
1015         DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
1016         status = gensec_update(gensec_security, mem_ctx, NULL, null_blob, auth_token);
1017
1018         if (!NT_STATUS_IS_OK(status) &&
1019             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1020         {
1021                 return status;
1022         }
1023
1024         if (client_hdr_signing == NULL) {
1025                 return status;
1026         }
1027
1028         if (cli->auth->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1029                 *client_hdr_signing = false;
1030                 return status;
1031         }
1032
1033         *client_hdr_signing = gensec_have_feature(gensec_security,
1034                                                 GENSEC_FEATURE_SIGN_PKT_HEADER);
1035
1036         return status;
1037 }
1038
1039 /*******************************************************************
1040  Creates the internals of a DCE/RPC bind request or alter context PDU.
1041  ********************************************************************/
1042
1043 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1044                                                 enum dcerpc_pkt_type ptype,
1045                                                 uint32 rpc_call_id,
1046                                                 const struct ndr_syntax_id *abstract,
1047                                                 const struct ndr_syntax_id *transfer,
1048                                                 const DATA_BLOB *auth_info,
1049                                                 bool client_hdr_signing,
1050                                                 DATA_BLOB *blob)
1051 {
1052         uint16 auth_len = auth_info->length;
1053         NTSTATUS status;
1054         union dcerpc_payload u;
1055         struct dcerpc_ctx_list ctx_list;
1056         uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1057
1058         if (auth_len) {
1059                 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1060         }
1061
1062         if (client_hdr_signing) {
1063                 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1064         }
1065
1066         ctx_list.context_id = 0;
1067         ctx_list.num_transfer_syntaxes = 1;
1068         ctx_list.abstract_syntax = *abstract;
1069         ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1070
1071         u.bind.max_xmit_frag    = RPC_MAX_PDU_FRAG_LEN;
1072         u.bind.max_recv_frag    = RPC_MAX_PDU_FRAG_LEN;
1073         u.bind.assoc_group_id   = 0x0;
1074         u.bind.num_contexts     = 1;
1075         u.bind.ctx_list         = &ctx_list;
1076         u.bind.auth_info        = *auth_info;
1077
1078         status = dcerpc_push_ncacn_packet(mem_ctx,
1079                                           ptype, pfc_flags,
1080                                           auth_len,
1081                                           rpc_call_id,
1082                                           &u,
1083                                           blob);
1084         if (!NT_STATUS_IS_OK(status)) {
1085                 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1086                 return status;
1087         }
1088
1089         return NT_STATUS_OK;
1090 }
1091
1092 /*******************************************************************
1093  Creates a DCE/RPC bind request.
1094  ********************************************************************/
1095
1096 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1097                                     struct rpc_pipe_client *cli,
1098                                     struct pipe_auth_data *auth,
1099                                     uint32 rpc_call_id,
1100                                     const struct ndr_syntax_id *abstract,
1101                                     const struct ndr_syntax_id *transfer,
1102                                     DATA_BLOB *rpc_out)
1103 {
1104         DATA_BLOB auth_token = data_blob_null;
1105         DATA_BLOB auth_info = data_blob_null;
1106         NTSTATUS ret = NT_STATUS_OK;
1107
1108         switch (auth->auth_type) {
1109         case DCERPC_AUTH_TYPE_SCHANNEL:
1110         case DCERPC_AUTH_TYPE_NTLMSSP:
1111         case DCERPC_AUTH_TYPE_KRB5:
1112         case DCERPC_AUTH_TYPE_SPNEGO:
1113                 ret = create_generic_auth_rpc_bind_req(cli, mem_ctx,
1114                                                        &auth_token,
1115                                                        &auth->client_hdr_signing);
1116
1117                 if (!NT_STATUS_IS_OK(ret) &&
1118                     !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1119                         return ret;
1120                 }
1121                 break;
1122
1123         case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1124                 auth_token = data_blob_talloc(mem_ctx,
1125                                               "NCALRPC_AUTH_TOKEN",
1126                                               18);
1127                 break;
1128
1129         case DCERPC_AUTH_TYPE_NONE:
1130                 break;
1131
1132         default:
1133                 /* "Can't" happen. */
1134                 return NT_STATUS_INVALID_INFO_CLASS;
1135         }
1136
1137         if (auth_token.length != 0) {
1138                 ret = dcerpc_push_dcerpc_auth(cli,
1139                                                 auth->auth_type,
1140                                                 auth->auth_level,
1141                                                 0, /* auth_pad_length */
1142                                                 1, /* auth_context_id */
1143                                                 &auth_token,
1144                                                 &auth_info);
1145                 if (!NT_STATUS_IS_OK(ret)) {
1146                         return ret;
1147                 }
1148                 data_blob_free(&auth_token);
1149         }
1150
1151         ret = create_bind_or_alt_ctx_internal(mem_ctx,
1152                                               DCERPC_PKT_BIND,
1153                                               rpc_call_id,
1154                                               abstract,
1155                                               transfer,
1156                                               &auth_info,
1157                                               auth->client_hdr_signing,
1158                                               rpc_out);
1159         return ret;
1160 }
1161
1162 /*******************************************************************
1163  External interface.
1164  Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1165  Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1166  and deals with signing/sealing details.
1167  ********************************************************************/
1168
1169 struct rpc_api_pipe_req_state {
1170         struct tevent_context *ev;
1171         struct rpc_pipe_client *cli;
1172         uint8_t op_num;
1173         uint32_t call_id;
1174         const DATA_BLOB *req_data;
1175         uint32_t req_data_sent;
1176         DATA_BLOB req_trailer;
1177         uint32_t req_trailer_sent;
1178         bool verify_bitmask1;
1179         bool verify_pcontext;
1180         DATA_BLOB rpc_out;
1181         DATA_BLOB reply_pdu;
1182 };
1183
1184 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1185 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1186 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state);
1187 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1188                                   bool *is_last_frag);
1189
1190 static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1191                                          struct tevent_context *ev,
1192                                          struct rpc_pipe_client *cli,
1193                                          uint8_t op_num,
1194                                          const DATA_BLOB *req_data)
1195 {
1196         struct tevent_req *req, *subreq;
1197         struct rpc_api_pipe_req_state *state;
1198         NTSTATUS status;
1199         bool is_last_frag;
1200
1201         req = tevent_req_create(mem_ctx, &state,
1202                                 struct rpc_api_pipe_req_state);
1203         if (req == NULL) {
1204                 return NULL;
1205         }
1206         state->ev = ev;
1207         state->cli = cli;
1208         state->op_num = op_num;
1209         state->req_data = req_data;
1210         state->req_data_sent = 0;
1211         state->call_id = get_rpc_call_id();
1212         state->reply_pdu = data_blob_null;
1213         state->rpc_out = data_blob_null;
1214
1215         if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1216                                         + RPC_MAX_SIGN_SIZE) {
1217                 /* Server is screwed up ! */
1218                 status = NT_STATUS_INVALID_PARAMETER;
1219                 goto post_status;
1220         }
1221
1222         status = prepare_verification_trailer(state);
1223         if (!NT_STATUS_IS_OK(status)) {
1224                 goto post_status;
1225         }
1226
1227         status = prepare_next_frag(state, &is_last_frag);
1228         if (!NT_STATUS_IS_OK(status)) {
1229                 goto post_status;
1230         }
1231
1232         if (is_last_frag) {
1233                 subreq = rpc_api_pipe_send(state, ev, state->cli,
1234                                            &state->rpc_out,
1235                                            DCERPC_PKT_RESPONSE,
1236                                            state->call_id);
1237                 if (subreq == NULL) {
1238                         goto fail;
1239                 }
1240                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1241         } else {
1242                 subreq = rpc_write_send(state, ev, cli->transport,
1243                                         state->rpc_out.data,
1244                                         state->rpc_out.length);
1245                 if (subreq == NULL) {
1246                         goto fail;
1247                 }
1248                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1249                                         req);
1250         }
1251         return req;
1252
1253  post_status:
1254         tevent_req_nterror(req, status);
1255         return tevent_req_post(req, ev);
1256  fail:
1257         TALLOC_FREE(req);
1258         return NULL;
1259 }
1260
1261 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state)
1262 {
1263         struct pipe_auth_data *a = state->cli->auth;
1264         struct dcerpc_sec_verification_trailer *t;
1265         struct dcerpc_sec_vt *c = NULL;
1266         struct ndr_push *ndr = NULL;
1267         enum ndr_err_code ndr_err;
1268         size_t align = 0;
1269         size_t pad = 0;
1270
1271         if (a == NULL) {
1272                 return NT_STATUS_OK;
1273         }
1274
1275         if (a->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1276                 return NT_STATUS_OK;
1277         }
1278
1279         t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1280         if (t == NULL) {
1281                 return NT_STATUS_NO_MEMORY;
1282         }
1283
1284         if (!a->verified_bitmask1) {
1285                 t->commands = talloc_realloc(t, t->commands,
1286                                              struct dcerpc_sec_vt,
1287                                              t->count.count + 1);
1288                 if (t->commands == NULL) {
1289                         return NT_STATUS_NO_MEMORY;
1290                 }
1291                 c = &t->commands[t->count.count++];
1292                 ZERO_STRUCTP(c);
1293
1294                 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1295                 if (a->client_hdr_signing) {
1296                         c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1297                 }
1298                 state->verify_bitmask1 = true;
1299         }
1300
1301         if (!state->cli->verified_pcontext) {
1302                 t->commands = talloc_realloc(t, t->commands,
1303                                              struct dcerpc_sec_vt,
1304                                              t->count.count + 1);
1305                 if (t->commands == NULL) {
1306                         return NT_STATUS_NO_MEMORY;
1307                 }
1308                 c = &t->commands[t->count.count++];
1309                 ZERO_STRUCTP(c);
1310
1311                 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1312                 c->u.pcontext.abstract_syntax = state->cli->abstract_syntax;
1313                 c->u.pcontext.transfer_syntax = state->cli->transfer_syntax;
1314
1315                 state->verify_pcontext = true;
1316         }
1317
1318         if (1|| !a->hdr_signing) {
1319                 t->commands = talloc_realloc(t, t->commands,
1320                                              struct dcerpc_sec_vt,
1321                                              t->count.count + 1);
1322                 if (t->commands == NULL) {
1323                         return NT_STATUS_NO_MEMORY;
1324                 }
1325                 c = &t->commands[t->count.count++];
1326                 ZERO_STRUCTP(c);
1327
1328                 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1329                 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1330                 c->u.header2.drep[0] = DCERPC_DREP_LE;
1331                 c->u.header2.drep[1] = 0;
1332                 c->u.header2.drep[2] = 0;
1333                 c->u.header2.drep[3] = 0;
1334                 {
1335                         static bool kaputtmachen = false;
1336                         if (kaputtmachen) {
1337                                 c->u.header2.drep[3] = 42;
1338                         }
1339                         kaputtmachen = !kaputtmachen;
1340                 }
1341                 c->u.header2.call_id = state->call_id;
1342                 c->u.header2.context_id = 0;
1343                 c->u.header2.opnum = state->op_num;
1344         }
1345
1346         if (t->count.count == 0) {
1347                 TALLOC_FREE(t);
1348                 return NT_STATUS_OK;
1349         }
1350
1351         c = &t->commands[t->count.count - 1];
1352         c->command |= DCERPC_SEC_VT_COMMAND_END;
1353
1354         if (DEBUGLEVEL >= 10) {
1355                 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1356         }
1357
1358         ndr = ndr_push_init_ctx(state);
1359         if (ndr == NULL) {
1360                 return NT_STATUS_NO_MEMORY;
1361         }
1362
1363         ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1364                                                 NDR_SCALARS | NDR_BUFFERS,
1365                                                 t);
1366         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1367                 return ndr_map_error2ntstatus(ndr_err);
1368         }
1369         state->req_trailer = ndr_push_blob(ndr);
1370
1371         align = state->req_data->length & 0x3;
1372         if (align > 0) {
1373                 pad = 4 - align;
1374         }
1375         if (pad > 0) {
1376                 bool ok;
1377                 uint8_t *p;
1378                 const uint8_t zeros[4] = { 0, };
1379
1380                 ok = data_blob_append(ndr, &state->req_trailer, zeros, pad);
1381                 if (!ok) {
1382                         return NT_STATUS_NO_MEMORY;
1383                 }
1384
1385                 /* move the padding to the start */
1386                 p = state->req_trailer.data;
1387                 memmove(p + pad, p, state->req_trailer.length - pad);
1388                 memset(p, 0, pad);
1389         }
1390
1391         return NT_STATUS_OK;
1392 }
1393
1394 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1395                                   bool *is_last_frag)
1396 {
1397         size_t auth_len;
1398         size_t frag_len;
1399         uint8_t flags = 0;
1400         size_t pad_len;
1401         size_t data_left;
1402         size_t data_thistime;
1403         size_t trailer_left;
1404         size_t trailer_thistime = 0;
1405         size_t total_left;
1406         size_t total_thistime;
1407         NTSTATUS status;
1408         bool ok;
1409         union dcerpc_payload u;
1410
1411         data_left = state->req_data->length - state->req_data_sent;
1412         trailer_left = state->req_trailer.length - state->req_trailer_sent;
1413         total_left = data_left + trailer_left;
1414         if ((total_left < data_left) || (total_left < trailer_left)) {
1415                 /*
1416                  * overflow
1417                  */
1418                 return NT_STATUS_INVALID_PARAMETER_MIX;
1419         }
1420
1421         status = dcerpc_guess_sizes(state->cli->auth,
1422                                     DCERPC_REQUEST_LENGTH, total_left,
1423                                     state->cli->max_xmit_frag,
1424                                     CLIENT_NDR_PADDING_SIZE,
1425                                     &total_thistime,
1426                                     &frag_len, &auth_len, &pad_len);
1427         if (!NT_STATUS_IS_OK(status)) {
1428                 return status;
1429         }
1430
1431         if (state->req_data_sent == 0) {
1432                 flags = DCERPC_PFC_FLAG_FIRST;
1433         }
1434
1435         if (total_thistime == total_left) {
1436                 flags |= DCERPC_PFC_FLAG_LAST;
1437         }
1438
1439         data_thistime = MIN(total_thistime, data_left);
1440         if (data_thistime < total_thistime) {
1441                 trailer_thistime = total_thistime - data_thistime;
1442         }
1443
1444         data_blob_free(&state->rpc_out);
1445
1446         ZERO_STRUCT(u.request);
1447
1448         u.request.alloc_hint    = total_left;
1449         u.request.context_id    = 0;
1450         u.request.opnum         = state->op_num;
1451
1452         if (!(flags & DCERPC_PFC_FLAG_FIRST)) {
1453                 u.request.opnum= 0xdead;
1454         }
1455
1456         status = dcerpc_push_ncacn_packet(state,
1457                                           DCERPC_PKT_REQUEST,
1458                                           flags,
1459                                           auth_len,
1460                                           state->call_id,
1461                                           &u,
1462                                           &state->rpc_out);
1463         if (!NT_STATUS_IS_OK(status)) {
1464                 return status;
1465         }
1466
1467         /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1468          * compute it right for requests because the auth trailer is missing
1469          * at this stage */
1470         dcerpc_set_frag_length(&state->rpc_out, frag_len);
1471
1472         if (data_thistime > 0) {
1473                 /* Copy in the data. */
1474                 ok = data_blob_append(NULL, &state->rpc_out,
1475                                 state->req_data->data + state->req_data_sent,
1476                                 data_thistime);
1477                 if (!ok) {
1478                         return NT_STATUS_NO_MEMORY;
1479                 }
1480                 state->req_data_sent += data_thistime;
1481         }
1482
1483         if (trailer_thistime > 0) {
1484                 /* Copy in the verification trailer. */
1485                 ok = data_blob_append(NULL, &state->rpc_out,
1486                                 state->req_trailer.data + state->req_trailer_sent,
1487                                 trailer_thistime);
1488                 if (!ok) {
1489                         return NT_STATUS_NO_MEMORY;
1490                 }
1491                 state->req_trailer_sent += trailer_thistime;
1492         }
1493
1494         switch (state->cli->auth->auth_level) {
1495         case DCERPC_AUTH_LEVEL_NONE:
1496         case DCERPC_AUTH_LEVEL_CONNECT:
1497         case DCERPC_AUTH_LEVEL_PACKET:
1498                 break;
1499         case DCERPC_AUTH_LEVEL_INTEGRITY:
1500         case DCERPC_AUTH_LEVEL_PRIVACY:
1501                 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1502                                                 &state->rpc_out);
1503                 if (!NT_STATUS_IS_OK(status)) {
1504                         return status;
1505                 }
1506                 break;
1507         default:
1508                 return NT_STATUS_INVALID_PARAMETER;
1509         }
1510
1511         *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1512
1513         return status;
1514 }
1515
1516 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1517 {
1518         struct tevent_req *req = tevent_req_callback_data(
1519                 subreq, struct tevent_req);
1520         struct rpc_api_pipe_req_state *state = tevent_req_data(
1521                 req, struct rpc_api_pipe_req_state);
1522         NTSTATUS status;
1523         bool is_last_frag;
1524
1525         status = rpc_write_recv(subreq);
1526         TALLOC_FREE(subreq);
1527         if (!NT_STATUS_IS_OK(status)) {
1528                 tevent_req_nterror(req, status);
1529                 return;
1530         }
1531
1532         status = prepare_next_frag(state, &is_last_frag);
1533         if (!NT_STATUS_IS_OK(status)) {
1534                 tevent_req_nterror(req, status);
1535                 return;
1536         }
1537
1538         if (is_last_frag) {
1539                 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1540                                            &state->rpc_out,
1541                                            DCERPC_PKT_RESPONSE,
1542                                            state->call_id);
1543                 if (tevent_req_nomem(subreq, req)) {
1544                         return;
1545                 }
1546                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1547         } else {
1548                 subreq = rpc_write_send(state, state->ev,
1549                                         state->cli->transport,
1550                                         state->rpc_out.data,
1551                                         state->rpc_out.length);
1552                 if (tevent_req_nomem(subreq, req)) {
1553                         return;
1554                 }
1555                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1556                                         req);
1557         }
1558 }
1559
1560 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1561 {
1562         struct tevent_req *req = tevent_req_callback_data(
1563                 subreq, struct tevent_req);
1564         struct rpc_api_pipe_req_state *state = tevent_req_data(
1565                 req, struct rpc_api_pipe_req_state);
1566         NTSTATUS status;
1567
1568         status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1569         TALLOC_FREE(subreq);
1570         if (!NT_STATUS_IS_OK(status)) {
1571                 tevent_req_nterror(req, status);
1572                 return;
1573         }
1574
1575         if (state->cli->auth == NULL) {
1576                 tevent_req_done(req);
1577                 return;
1578         }
1579
1580         if (state->verify_bitmask1) {
1581                 state->cli->auth->verified_bitmask1 = true;
1582         }
1583
1584         if (state->verify_pcontext) {
1585                 state->cli->verified_pcontext = true;
1586         }
1587
1588         tevent_req_done(req);
1589 }
1590
1591 static NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1592                                DATA_BLOB *reply_pdu)
1593 {
1594         struct rpc_api_pipe_req_state *state = tevent_req_data(
1595                 req, struct rpc_api_pipe_req_state);
1596         NTSTATUS status;
1597
1598         if (tevent_req_is_nterror(req, &status)) {
1599                 /*
1600                  * We always have to initialize to reply pdu, even if there is
1601                  * none. The rpccli_* caller routines expect this.
1602                  */
1603                 *reply_pdu = data_blob_null;
1604                 return status;
1605         }
1606
1607         /* return data to caller and assign it ownership of memory */
1608         reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1609         reply_pdu->length = state->reply_pdu.length;
1610         state->reply_pdu.length = 0;
1611
1612         return NT_STATUS_OK;
1613 }
1614
1615 /****************************************************************************
1616  Check the rpc bind acknowledge response.
1617 ****************************************************************************/
1618
1619 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1620                                 const struct ndr_syntax_id *transfer)
1621 {
1622         struct dcerpc_ack_ctx ctx;
1623
1624         if (r->secondary_address_size == 0) {
1625                 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1626         }
1627
1628         if (r->num_results < 1 || !r->ctx_list) {
1629                 return false;
1630         }
1631
1632         ctx = r->ctx_list[0];
1633
1634         /* check the transfer syntax */
1635         if ((ctx.syntax.if_version != transfer->if_version) ||
1636              (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1637                 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1638                 return False;
1639         }
1640
1641         if (r->num_results != 0x1 || ctx.result != 0) {
1642                 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1643                           r->num_results, ctx.reason.value));
1644         }
1645
1646         DEBUG(5,("check_bind_response: accepted!\n"));
1647         return True;
1648 }
1649
1650 /*******************************************************************
1651  Creates a DCE/RPC bind authentication response.
1652  This is the packet that is sent back to the server once we
1653  have received a BIND-ACK, to finish the third leg of
1654  the authentication handshake.
1655  ********************************************************************/
1656
1657 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1658                                 struct rpc_pipe_client *cli,
1659                                 uint32 rpc_call_id,
1660                                 enum dcerpc_AuthType auth_type,
1661                                 enum dcerpc_AuthLevel auth_level,
1662                                 DATA_BLOB *pauth_blob,
1663                                 DATA_BLOB *rpc_out)
1664 {
1665         NTSTATUS status;
1666         union dcerpc_payload u;
1667
1668         u.auth3._pad = 0;
1669
1670         status = dcerpc_push_dcerpc_auth(mem_ctx,
1671                                          auth_type,
1672                                          auth_level,
1673                                          0, /* auth_pad_length */
1674                                          1, /* auth_context_id */
1675                                          pauth_blob,
1676                                          &u.auth3.auth_info);
1677         if (!NT_STATUS_IS_OK(status)) {
1678                 return status;
1679         }
1680
1681         status = dcerpc_push_ncacn_packet(mem_ctx,
1682                                           DCERPC_PKT_AUTH3,
1683                                           DCERPC_PFC_FLAG_FIRST |
1684                                           DCERPC_PFC_FLAG_LAST,
1685                                           pauth_blob->length,
1686                                           rpc_call_id,
1687                                           &u,
1688                                           rpc_out);
1689         data_blob_free(&u.auth3.auth_info);
1690         if (!NT_STATUS_IS_OK(status)) {
1691                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1692                 return status;
1693         }
1694
1695         return NT_STATUS_OK;
1696 }
1697
1698 /*******************************************************************
1699  Creates a DCE/RPC bind alter context authentication request which
1700  may contain a spnego auth blobl
1701  ********************************************************************/
1702
1703 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1704                                         enum dcerpc_AuthType auth_type,
1705                                         enum dcerpc_AuthLevel auth_level,
1706                                         uint32 rpc_call_id,
1707                                         const struct ndr_syntax_id *abstract,
1708                                         const struct ndr_syntax_id *transfer,
1709                                         const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1710                                         DATA_BLOB *rpc_out)
1711 {
1712         DATA_BLOB auth_info;
1713         NTSTATUS status;
1714
1715         status = dcerpc_push_dcerpc_auth(mem_ctx,
1716                                          auth_type,
1717                                          auth_level,
1718                                          0, /* auth_pad_length */
1719                                          1, /* auth_context_id */
1720                                          pauth_blob,
1721                                          &auth_info);
1722         if (!NT_STATUS_IS_OK(status)) {
1723                 return status;
1724         }
1725
1726         status = create_bind_or_alt_ctx_internal(mem_ctx,
1727                                                  DCERPC_PKT_ALTER,
1728                                                  rpc_call_id,
1729                                                  abstract,
1730                                                  transfer,
1731                                                  &auth_info,
1732                                                  false, /* client_hdr_signing */
1733                                                  rpc_out);
1734         data_blob_free(&auth_info);
1735         return status;
1736 }
1737
1738 /****************************************************************************
1739  Do an rpc bind.
1740 ****************************************************************************/
1741
1742 struct rpc_pipe_bind_state {
1743         struct tevent_context *ev;
1744         struct rpc_pipe_client *cli;
1745         DATA_BLOB rpc_out;
1746         bool auth3;
1747         uint32_t rpc_call_id;
1748 };
1749
1750 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1751 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1752                                    struct rpc_pipe_bind_state *state,
1753                                    DATA_BLOB *credentials);
1754 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1755                                      struct rpc_pipe_bind_state *state,
1756                                      DATA_BLOB *credentials);
1757
1758 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1759                                       struct tevent_context *ev,
1760                                       struct rpc_pipe_client *cli,
1761                                       struct pipe_auth_data *auth)
1762 {
1763         struct tevent_req *req, *subreq;
1764         struct rpc_pipe_bind_state *state;
1765         NTSTATUS status;
1766
1767         req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1768         if (req == NULL) {
1769                 return NULL;
1770         }
1771
1772         DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1773                 rpccli_pipe_txt(talloc_tos(), cli),
1774                 (unsigned int)auth->auth_type,
1775                 (unsigned int)auth->auth_level ));
1776
1777         state->ev = ev;
1778         state->cli = cli;
1779         state->rpc_call_id = get_rpc_call_id();
1780
1781         cli->auth = talloc_move(cli, &auth);
1782
1783         /* Marshall the outgoing data. */
1784         status = create_rpc_bind_req(state, cli,
1785                                      cli->auth,
1786                                      state->rpc_call_id,
1787                                      &cli->abstract_syntax,
1788                                      &cli->transfer_syntax,
1789                                      &state->rpc_out);
1790
1791         if (!NT_STATUS_IS_OK(status) &&
1792             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1793                 goto post_status;
1794         }
1795
1796         subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1797                                    DCERPC_PKT_BIND_ACK, state->rpc_call_id);
1798         if (subreq == NULL) {
1799                 goto fail;
1800         }
1801         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1802         return req;
1803
1804  post_status:
1805         tevent_req_nterror(req, status);
1806         return tevent_req_post(req, ev);
1807  fail:
1808         TALLOC_FREE(req);
1809         return NULL;
1810 }
1811
1812 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1813 {
1814         struct tevent_req *req = tevent_req_callback_data(
1815                 subreq, struct tevent_req);
1816         struct rpc_pipe_bind_state *state = tevent_req_data(
1817                 req, struct rpc_pipe_bind_state);
1818         struct pipe_auth_data *pauth = state->cli->auth;
1819         struct gensec_security *gensec_security;
1820         struct ncacn_packet *pkt = NULL;
1821         struct dcerpc_auth auth;
1822         DATA_BLOB auth_token = data_blob_null;
1823         NTSTATUS status;
1824
1825         status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
1826         TALLOC_FREE(subreq);
1827         if (!NT_STATUS_IS_OK(status)) {
1828                 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1829                           rpccli_pipe_txt(talloc_tos(), state->cli),
1830                           nt_errstr(status)));
1831                 tevent_req_nterror(req, status);
1832                 return;
1833         }
1834
1835         if (state->auth3) {
1836                 tevent_req_done(req);
1837                 return;
1838         }
1839
1840         if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1841                 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1842                 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1843                 return;
1844         }
1845
1846         state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1847         state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1848
1849         switch(pauth->auth_type) {
1850
1851         case DCERPC_AUTH_TYPE_NONE:
1852         case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1853                 /* Bind complete. */
1854                 tevent_req_done(req);
1855                 return;
1856
1857         case DCERPC_AUTH_TYPE_SCHANNEL:
1858         case DCERPC_AUTH_TYPE_NTLMSSP:
1859         case DCERPC_AUTH_TYPE_SPNEGO:
1860         case DCERPC_AUTH_TYPE_KRB5:
1861                 /* Paranoid lenght checks */
1862                 if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH
1863                                                 + pkt->auth_length) {
1864                         tevent_req_nterror(req,
1865                                         NT_STATUS_INFO_LENGTH_MISMATCH);
1866                         return;
1867                 }
1868                 /* get auth credentials */
1869                 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
1870                                                  &pkt->u.bind_ack.auth_info,
1871                                                  &auth, false);
1872                 if (!NT_STATUS_IS_OK(status)) {
1873                         DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1874                                   nt_errstr(status)));
1875                         tevent_req_nterror(req, status);
1876                         return;
1877                 }
1878                 break;
1879
1880         default:
1881                 goto err_out;
1882         }
1883
1884         /*
1885          * For authenticated binds we may need to do 3 or 4 leg binds.
1886          */
1887
1888         switch(pauth->auth_type) {
1889
1890         case DCERPC_AUTH_TYPE_NONE:
1891         case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1892                 /* Bind complete. */
1893                 tevent_req_done(req);
1894                 return;
1895
1896         case DCERPC_AUTH_TYPE_SCHANNEL:
1897         case DCERPC_AUTH_TYPE_NTLMSSP:
1898         case DCERPC_AUTH_TYPE_KRB5:
1899         case DCERPC_AUTH_TYPE_SPNEGO:
1900                 gensec_security = talloc_get_type_abort(pauth->auth_ctx,
1901                                                 struct gensec_security);
1902
1903                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1904                         if (pauth->client_hdr_signing) {
1905                                 pauth->hdr_signing = true;
1906                                 gensec_want_feature(gensec_security,
1907                                                     GENSEC_FEATURE_SIGN_PKT_HEADER);
1908                         }
1909                 }
1910
1911                 status = gensec_update(gensec_security, state, NULL,
1912                                        auth.credentials, &auth_token);
1913                 if (NT_STATUS_EQUAL(status,
1914                                     NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1915                         status = rpc_bind_next_send(req, state,
1916                                                         &auth_token);
1917                 } else if (NT_STATUS_IS_OK(status)) {
1918                         if (auth_token.length == 0) {
1919                                 /* Bind complete. */
1920                                 tevent_req_done(req);
1921                                 return;
1922                         }
1923                         status = rpc_bind_finish_send(req, state,
1924                                                         &auth_token);
1925                 }
1926                 break;
1927
1928         default:
1929                 goto err_out;
1930         }
1931
1932         if (!NT_STATUS_IS_OK(status)) {
1933                 tevent_req_nterror(req, status);
1934         }
1935         return;
1936
1937 err_out:
1938         DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
1939                  (unsigned int)state->cli->auth->auth_type));
1940         tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1941 }
1942
1943 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1944                                    struct rpc_pipe_bind_state *state,
1945                                    DATA_BLOB *auth_token)
1946 {
1947         struct pipe_auth_data *auth = state->cli->auth;
1948         struct tevent_req *subreq;
1949         NTSTATUS status;
1950
1951         /* Now prepare the alter context pdu. */
1952         data_blob_free(&state->rpc_out);
1953
1954         status = create_rpc_alter_context(state,
1955                                           auth->auth_type,
1956                                           auth->auth_level,
1957                                           state->rpc_call_id,
1958                                           &state->cli->abstract_syntax,
1959                                           &state->cli->transfer_syntax,
1960                                           auth_token,
1961                                           &state->rpc_out);
1962         if (!NT_STATUS_IS_OK(status)) {
1963                 return status;
1964         }
1965
1966         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1967                                    &state->rpc_out, DCERPC_PKT_ALTER_RESP,
1968                                    state->rpc_call_id);
1969         if (subreq == NULL) {
1970                 return NT_STATUS_NO_MEMORY;
1971         }
1972         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1973         return NT_STATUS_OK;
1974 }
1975
1976 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1977                                      struct rpc_pipe_bind_state *state,
1978                                      DATA_BLOB *auth_token)
1979 {
1980         struct pipe_auth_data *auth = state->cli->auth;
1981         struct tevent_req *subreq;
1982         NTSTATUS status;
1983
1984         state->auth3 = true;
1985
1986         /* Now prepare the auth3 context pdu. */
1987         data_blob_free(&state->rpc_out);
1988
1989         status = create_rpc_bind_auth3(state, state->cli,
1990                                         state->rpc_call_id,
1991                                         auth->auth_type,
1992                                         auth->auth_level,
1993                                         auth_token,
1994                                         &state->rpc_out);
1995         if (!NT_STATUS_IS_OK(status)) {
1996                 return status;
1997         }
1998
1999         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2000                                    &state->rpc_out, DCERPC_PKT_AUTH3,
2001                                    state->rpc_call_id);
2002         if (subreq == NULL) {
2003                 return NT_STATUS_NO_MEMORY;
2004         }
2005         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2006         return NT_STATUS_OK;
2007 }
2008
2009 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2010 {
2011         return tevent_req_simple_recv_ntstatus(req);
2012 }
2013
2014 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2015                        struct pipe_auth_data *auth)
2016 {
2017         TALLOC_CTX *frame = talloc_stackframe();
2018         struct tevent_context *ev;
2019         NTSTATUS status = NT_STATUS_OK;
2020         struct dcerpc_call *call;
2021         struct tevent_req *subreq;
2022         struct dcerpc_presentation *pres[1];
2023
2024         ev = samba_tevent_context_init(frame);
2025         if (ev == NULL) {
2026                 status = NT_STATUS_NO_MEMORY;
2027                 goto fail;
2028         }
2029
2030         cli->sec = dcerpc_security_allocate(cli, cli->conn,
2031                                            auth->auth_type,
2032                                            auth->auth_level,
2033                                            auth->auth_ctx);
2034
2035         call = dcerpc_call_allocate(frame, cli->assoc, NULL, NULL);
2036
2037         pres[0] = cli->pres;
2038
2039         subreq = dcerpc_do_bind_send(frame, ev, cli->conn, call,
2040                                      cli->sec, ARRAY_SIZE(pres), pres);
2041
2042         if (subreq == NULL) {
2043                 status = NT_STATUS_NO_MEMORY;
2044                 goto fail;
2045         }
2046
2047         if (!tevent_req_poll(subreq, ev)) {
2048                 status = map_nt_error_from_unix(errno);
2049                 goto fail;
2050         }
2051
2052         status = dcerpc_do_bind_recv(subreq);
2053  fail:
2054         TALLOC_FREE(frame);
2055         return status;
2056 }
2057
2058 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2059
2060 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2061                                 unsigned int timeout)
2062 {
2063         unsigned int old;
2064
2065         if (rpc_cli->transport == NULL) {
2066                 return RPCCLI_DEFAULT_TIMEOUT;
2067         }
2068
2069         if (rpc_cli->transport->set_timeout == NULL) {
2070                 return RPCCLI_DEFAULT_TIMEOUT;
2071         }
2072
2073         old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2074         if (old == 0) {
2075                 return RPCCLI_DEFAULT_TIMEOUT;
2076         }
2077
2078         return old;
2079 }
2080
2081 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2082 {
2083         if (rpc_cli == NULL) {
2084                 return false;
2085         }
2086
2087         if (rpc_cli->transport == NULL) {
2088                 return false;
2089         }
2090
2091         return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2092 }
2093
2094 struct rpccli_bh_state {
2095         struct rpc_pipe_client *rpc_cli;
2096 };
2097
2098 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2099 {
2100         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2101                                      struct rpccli_bh_state);
2102
2103         return rpccli_is_connected(hs->rpc_cli);
2104 }
2105
2106 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2107                                       uint32_t timeout)
2108 {
2109         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2110                                      struct rpccli_bh_state);
2111
2112         return rpccli_set_timeout(hs->rpc_cli, timeout);
2113 }
2114
2115 static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
2116                                 enum dcerpc_AuthType *auth_type,
2117                                 enum dcerpc_AuthLevel *auth_level)
2118 {
2119         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2120                                      struct rpccli_bh_state);
2121
2122         if (hs->rpc_cli == NULL) {
2123                 return;
2124         }
2125
2126         if (hs->rpc_cli->auth == NULL) {
2127                 return;
2128         }
2129
2130         *auth_type = hs->rpc_cli->auth->auth_type;
2131         *auth_level = hs->rpc_cli->auth->auth_level;
2132 }
2133
2134 struct rpccli_bh_raw_call_state {
2135         struct dcerpc_call *call;
2136         DATA_BLOB in_data;
2137         DATA_BLOB out_data;
2138         uint32_t out_flags;
2139 };
2140
2141 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2142
2143 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2144                                                   struct tevent_context *ev,
2145                                                   struct dcerpc_binding_handle *h,
2146                                                   const struct GUID *object,
2147                                                   uint32_t opnum,
2148                                                   uint32_t in_flags,
2149                                                   const uint8_t *in_data,
2150                                                   size_t in_length)
2151 {
2152         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2153                                      struct rpccli_bh_state);
2154         struct tevent_req *req;
2155         struct rpccli_bh_raw_call_state *state;
2156         bool ok;
2157         struct tevent_req *subreq;
2158         bool bigendian = false;
2159
2160         req = tevent_req_create(mem_ctx, &state,
2161                                 struct rpccli_bh_raw_call_state);
2162         if (req == NULL) {
2163                 return NULL;
2164         }
2165         state->in_data.data = discard_const_p(uint8_t, in_data);
2166         state->in_data.length = in_length;
2167
2168         ok = rpccli_bh_is_connected(h);
2169         if (!ok) {
2170                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2171                 return tevent_req_post(req, ev);
2172         }
2173
2174         state->call = dcerpc_call_allocate(state,
2175                                            hs->rpc_cli->assoc,
2176                                            hs->rpc_cli->sec,
2177                                            hs->rpc_cli->pres);
2178
2179         if (in_flags & LIBNDR_FLAG_BIGENDIAN) {
2180                 bigendian = true;
2181         }
2182
2183         subreq = dcerpc_do_request_send(state, ev, hs->rpc_cli->conn,
2184                                         state->call, NULL, opnum,
2185                                         &state->in_data, bigendian);
2186 //      subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2187 //                                     opnum, &state->in_data);
2188         if (tevent_req_nomem(subreq, req)) {
2189                 return tevent_req_post(req, ev);
2190         }
2191         tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2192
2193         return req;
2194 }
2195
2196 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2197 {
2198         struct tevent_req *req =
2199                 tevent_req_callback_data(subreq,
2200                 struct tevent_req);
2201         struct rpccli_bh_raw_call_state *state =
2202                 tevent_req_data(req,
2203                 struct rpccli_bh_raw_call_state);
2204         NTSTATUS status;
2205         bool bigendian = false;
2206
2207         state->out_flags = 0;
2208
2209         /* TODO: support bigendian responses */
2210
2211         status = dcerpc_do_request_recv(subreq, state, &state->out_data,
2212                                         &bigendian);
2213         //status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2214         TALLOC_FREE(subreq);
2215         if (!NT_STATUS_IS_OK(status)) {
2216                 tevent_req_nterror(req, status);
2217                 return;
2218         }
2219
2220         if (bigendian) {
2221                 state->out_flags |= LIBNDR_FLAG_BIGENDIAN;
2222         }
2223
2224         tevent_req_done(req);
2225 }
2226
2227 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2228                                         TALLOC_CTX *mem_ctx,
2229                                         uint8_t **out_data,
2230                                         size_t *out_length,
2231                                         uint32_t *out_flags)
2232 {
2233         struct rpccli_bh_raw_call_state *state =
2234                 tevent_req_data(req,
2235                 struct rpccli_bh_raw_call_state);
2236         NTSTATUS status;
2237
2238         if (tevent_req_is_nterror(req, &status)) {
2239                 tevent_req_received(req);
2240                 return status;
2241         }
2242
2243         *out_data = talloc_move(mem_ctx, &state->out_data.data);
2244         *out_length = state->out_data.length;
2245         *out_flags = state->out_flags;
2246         tevent_req_received(req);
2247         return NT_STATUS_OK;
2248 }
2249
2250 struct rpccli_bh_disconnect_state {
2251         uint8_t _dummy;
2252 };
2253
2254 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2255                                                 struct tevent_context *ev,
2256                                                 struct dcerpc_binding_handle *h)
2257 {
2258         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2259                                      struct rpccli_bh_state);
2260         struct tevent_req *req;
2261         struct rpccli_bh_disconnect_state *state;
2262         bool ok;
2263
2264         req = tevent_req_create(mem_ctx, &state,
2265                                 struct rpccli_bh_disconnect_state);
2266         if (req == NULL) {
2267                 return NULL;
2268         }
2269
2270         ok = rpccli_bh_is_connected(h);
2271         if (!ok) {
2272                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2273                 return tevent_req_post(req, ev);
2274         }
2275
2276         /*
2277          * TODO: do a real async disconnect ...
2278          *
2279          * For now the caller needs to free rpc_cli
2280          */
2281         hs->rpc_cli = NULL;
2282
2283         tevent_req_done(req);
2284         return tevent_req_post(req, ev);
2285 }
2286
2287 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2288 {
2289         NTSTATUS status;
2290
2291         if (tevent_req_is_nterror(req, &status)) {
2292                 tevent_req_received(req);
2293                 return status;
2294         }
2295
2296         tevent_req_received(req);
2297         return NT_STATUS_OK;
2298 }
2299
2300 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2301 {
2302         return true;
2303 }
2304
2305 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2306                                    int ndr_flags,
2307                                    const void *_struct_ptr,
2308                                    const struct ndr_interface_call *call)
2309 {
2310         void *struct_ptr = discard_const(_struct_ptr);
2311
2312         if (DEBUGLEVEL < 10) {
2313                 return;
2314         }
2315
2316         if (ndr_flags & NDR_IN) {
2317                 ndr_print_function_debug(call->ndr_print,
2318                                          call->name,
2319                                          ndr_flags,
2320                                          struct_ptr);
2321         }
2322         if (ndr_flags & NDR_OUT) {
2323                 ndr_print_function_debug(call->ndr_print,
2324                                          call->name,
2325                                          ndr_flags,
2326                                          struct_ptr);
2327         }
2328 }
2329
2330 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2331         .name                   = "rpccli",
2332         .is_connected           = rpccli_bh_is_connected,
2333         .set_timeout            = rpccli_bh_set_timeout,
2334         .auth_info              = rpccli_bh_auth_info,
2335         .raw_call_send          = rpccli_bh_raw_call_send,
2336         .raw_call_recv          = rpccli_bh_raw_call_recv,
2337         .disconnect_send        = rpccli_bh_disconnect_send,
2338         .disconnect_recv        = rpccli_bh_disconnect_recv,
2339
2340         .ref_alloc              = rpccli_bh_ref_alloc,
2341         .do_ndr_print           = rpccli_bh_do_ndr_print,
2342 };
2343
2344 /* initialise a rpc_pipe_client binding handle */
2345 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2346                                         const struct GUID *object,
2347                                         const struct ndr_interface_table *table)
2348 {
2349         struct dcerpc_binding_handle *h;
2350         struct rpccli_bh_state *hs;
2351
2352         h = dcerpc_binding_handle_create(c,
2353                                          &rpccli_bh_ops,
2354                                          object,
2355                                          table,
2356                                          &hs,
2357                                          struct rpccli_bh_state,
2358                                          __location__);
2359         if (h == NULL) {
2360                 return NULL;
2361         }
2362         hs->rpc_cli = c;
2363
2364         return h;
2365 }
2366
2367 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2368                                   struct pipe_auth_data **presult)
2369 {
2370         struct pipe_auth_data *result;
2371
2372         result = talloc_zero(mem_ctx, struct pipe_auth_data);
2373         if (result == NULL) {
2374                 return NT_STATUS_NO_MEMORY;
2375         }
2376
2377         result->auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM;
2378         result->auth_level = DCERPC_AUTH_LEVEL_CONNECT;
2379
2380         result->user_name = talloc_strdup(result, "");
2381         result->domain = talloc_strdup(result, "");
2382         if ((result->user_name == NULL) || (result->domain == NULL)) {
2383                 TALLOC_FREE(result);
2384                 return NT_STATUS_NO_MEMORY;
2385         }
2386
2387         *presult = result;
2388         return NT_STATUS_OK;
2389 }
2390
2391 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2392                                struct pipe_auth_data **presult)
2393 {
2394         struct pipe_auth_data *result;
2395
2396         result = talloc_zero(mem_ctx, struct pipe_auth_data);
2397         if (result == NULL) {
2398                 return NT_STATUS_NO_MEMORY;
2399         }
2400
2401         result->auth_type = DCERPC_AUTH_TYPE_NONE;
2402         result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2403
2404         result->user_name = talloc_strdup(result, "");
2405         result->domain = talloc_strdup(result, "");
2406         if ((result->user_name == NULL) || (result->domain == NULL)) {
2407                 TALLOC_FREE(result);
2408                 return NT_STATUS_NO_MEMORY;
2409         }
2410
2411         *presult = result;
2412         return NT_STATUS_OK;
2413 }
2414
2415 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2416                                          enum dcerpc_AuthType auth_type,
2417                                          enum dcerpc_AuthLevel auth_level,
2418                                          const char *server,
2419                                          const char *target_service,
2420                                          const char *domain,
2421                                          const char *username,
2422                                          const char *password,
2423                                          enum credentials_use_kerberos use_kerberos,
2424                                          struct netlogon_creds_CredentialState *creds,
2425                                          struct pipe_auth_data **presult)
2426 {
2427         struct auth_generic_state *auth_generic_ctx;
2428         struct pipe_auth_data *result;
2429         NTSTATUS status;
2430
2431         result = talloc_zero(mem_ctx, struct pipe_auth_data);
2432         if (result == NULL) {
2433                 return NT_STATUS_NO_MEMORY;
2434         }
2435
2436         result->auth_type = auth_type;
2437         result->auth_level = auth_level;
2438
2439         result->user_name = talloc_strdup(result, username);
2440         result->domain = talloc_strdup(result, domain);
2441         if ((result->user_name == NULL) || (result->domain == NULL)) {
2442                 status = NT_STATUS_NO_MEMORY;
2443                 goto fail;
2444         }
2445
2446         status = auth_generic_client_prepare(result,
2447                                              &auth_generic_ctx);
2448         if (!NT_STATUS_IS_OK(status)) {
2449                 goto fail;
2450         }
2451
2452         status = auth_generic_set_username(auth_generic_ctx, username);
2453         if (!NT_STATUS_IS_OK(status)) {
2454                 goto fail;
2455         }
2456
2457         status = auth_generic_set_domain(auth_generic_ctx, domain);
2458         if (!NT_STATUS_IS_OK(status)) {
2459                 goto fail;
2460         }
2461
2462         status = auth_generic_set_password(auth_generic_ctx, password);
2463         if (!NT_STATUS_IS_OK(status)) {
2464                 goto fail;
2465         }
2466
2467         status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2468         if (!NT_STATUS_IS_OK(status)) {
2469                 goto fail;
2470         }
2471
2472         status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2473         if (!NT_STATUS_IS_OK(status)) {
2474                 goto fail;
2475         }
2476
2477         cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos);
2478         cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
2479
2480         status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2481         if (!NT_STATUS_IS_OK(status)) {
2482                 goto fail;
2483         }
2484
2485         result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2486         talloc_free(auth_generic_ctx);
2487         *presult = result;
2488         return NT_STATUS_OK;
2489
2490  fail:
2491         TALLOC_FREE(result);
2492         return status;
2493 }
2494
2495 /**
2496  * Create an rpc pipe client struct, connecting to a tcp port.
2497  */
2498 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2499                                        const struct sockaddr_storage *ss_addr,
2500                                        uint16_t port,
2501                                        const struct ndr_interface_table *table,
2502                                        struct rpc_pipe_client **presult)
2503 {
2504         struct rpc_pipe_client *result;
2505         struct sockaddr_storage addr;
2506         NTSTATUS status;
2507         int fd;
2508
2509         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2510         if (result == NULL) {
2511                 return NT_STATUS_NO_MEMORY;
2512         }
2513
2514         result->abstract_syntax = table->syntax_id;
2515         result->transfer_syntax = ndr_transfer_syntax_ndr;
2516
2517         result->desthost = talloc_strdup(result, host);
2518         result->srv_name_slash = talloc_asprintf_strupper_m(
2519                 result, "\\\\%s", result->desthost);
2520         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2521                 status = NT_STATUS_NO_MEMORY;
2522                 goto fail;
2523         }
2524
2525         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2526         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2527
2528         if (ss_addr == NULL) {
2529                 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2530                         status = NT_STATUS_NOT_FOUND;
2531                         goto fail;
2532                 }
2533         } else {
2534                 addr = *ss_addr;
2535         }
2536
2537         status = open_socket_out(&addr, port, 60*1000, &fd);
2538         if (!NT_STATUS_IS_OK(status)) {
2539                 goto fail;
2540         }
2541         set_socket_options(fd, lp_socket_options());
2542
2543         status = rpc_transport_sock_init(result, fd, &result->transport);
2544         if (!NT_STATUS_IS_OK(status)) {
2545                 close(fd);
2546                 goto fail;
2547         }
2548
2549         result->transport->transport = NCACN_IP_TCP;
2550
2551         result->assoc = dcerpc_association_create(result, 0);
2552         result->conn = dcerpc_connection_create(result, result->assoc,
2553                                                 &result->transport->stream);
2554         result->pres = dcerpc_presentation_allocate(result, result->conn, table,
2555                                                     &ndr_transfer_syntax_ndr);
2556         result->sec = dcerpc_security_allocate(result, result->conn,
2557                                                DCERPC_AUTH_TYPE_NONE,
2558                                                DCERPC_AUTH_LEVEL_NONE,
2559                                                NULL);
2560
2561         result->binding_handle = rpccli_bh_create(result, NULL, table);
2562         if (result->binding_handle == NULL) {
2563                 TALLOC_FREE(result);
2564                 return NT_STATUS_NO_MEMORY;
2565         }
2566
2567         *presult = result;
2568         return NT_STATUS_OK;
2569
2570  fail:
2571         TALLOC_FREE(result);
2572         return status;
2573 }
2574
2575 /**
2576  * Determine the tcp port on which a dcerpc interface is listening
2577  * for the ncacn_ip_tcp transport via the endpoint mapper of the
2578  * target host.
2579  */
2580 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2581                                       const struct sockaddr_storage *addr,
2582                                       const struct ndr_interface_table *table,
2583                                       uint16_t *pport)
2584 {
2585         NTSTATUS status;
2586         struct rpc_pipe_client *epm_pipe = NULL;
2587         struct dcerpc_binding_handle *epm_handle = NULL;
2588         struct pipe_auth_data *auth = NULL;
2589         struct dcerpc_binding *map_binding = NULL;
2590         struct dcerpc_binding *res_binding = NULL;
2591         struct epm_twr_t *map_tower = NULL;
2592         struct epm_twr_t *res_towers = NULL;
2593         struct policy_handle *entry_handle = NULL;
2594         uint32_t num_towers = 0;
2595         uint32_t max_towers = 1;
2596         struct epm_twr_p_t towers;
2597         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2598         uint32_t result = 0;
2599
2600         if (pport == NULL) {
2601                 status = NT_STATUS_INVALID_PARAMETER;
2602                 goto done;
2603         }
2604
2605         if (ndr_syntax_id_equal(&table->syntax_id,
2606                                 &ndr_table_epmapper.syntax_id)) {
2607                 *pport = 135;
2608                 status = NT_STATUS_OK;
2609                 goto done;
2610         }
2611
2612         /* open the connection to the endpoint mapper */
2613         status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2614                                         &ndr_table_epmapper,
2615                                         &epm_pipe);
2616
2617         if (!NT_STATUS_IS_OK(status)) {
2618                 goto done;
2619         }
2620         epm_handle = epm_pipe->binding_handle;
2621
2622         status = rpccli_anon_bind_data(tmp_ctx, &auth);
2623         if (!NT_STATUS_IS_OK(status)) {
2624                 goto done;
2625         }
2626
2627         status = rpc_pipe_bind(epm_pipe, auth);
2628         if (!NT_STATUS_IS_OK(status)) {
2629                 goto done;
2630         }
2631
2632         /* create tower for asking the epmapper */
2633
2634         map_binding = talloc_zero(tmp_ctx, struct dcerpc_binding);
2635         if (map_binding == NULL) {
2636                 status = NT_STATUS_NO_MEMORY;
2637                 goto done;
2638         }
2639
2640         map_binding->transport = NCACN_IP_TCP;
2641         map_binding->object = table->syntax_id;
2642         map_binding->host = host; /* needed? */
2643         map_binding->endpoint = "0"; /* correct? needed? */
2644
2645         map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
2646         if (map_tower == NULL) {
2647                 status = NT_STATUS_NO_MEMORY;
2648                 goto done;
2649         }
2650
2651         status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2652                                             &(map_tower->tower));
2653         if (!NT_STATUS_IS_OK(status)) {
2654                 goto done;
2655         }
2656
2657         /* allocate further parameters for the epm_Map call */
2658
2659         res_towers = talloc_array(tmp_ctx, struct epm_twr_t, max_towers);
2660         if (res_towers == NULL) {
2661                 status = NT_STATUS_NO_MEMORY;
2662                 goto done;
2663         }
2664         towers.twr = res_towers;
2665
2666         entry_handle = talloc_zero(tmp_ctx, struct policy_handle);
2667         if (entry_handle == NULL) {
2668                 status = NT_STATUS_NO_MEMORY;
2669                 goto done;
2670         }
2671
2672         /* ask the endpoint mapper for the port */
2673
2674         status = dcerpc_epm_Map(epm_handle,
2675                                 tmp_ctx,
2676                                 discard_const_p(struct GUID,
2677                                               &(table->syntax_id.uuid)),
2678                                 map_tower,
2679                                 entry_handle,
2680                                 max_towers,
2681                                 &num_towers,
2682                                 &towers,
2683                                 &result);
2684
2685         if (!NT_STATUS_IS_OK(status)) {
2686                 goto done;
2687         }
2688
2689         if (result != EPMAPPER_STATUS_OK) {
2690                 status = NT_STATUS_UNSUCCESSFUL;
2691                 goto done;
2692         }
2693
2694         if (num_towers != 1) {
2695                 status = NT_STATUS_UNSUCCESSFUL;
2696                 goto done;
2697         }
2698
2699         /* extract the port from the answer */
2700
2701         status = dcerpc_binding_from_tower(tmp_ctx,
2702                                            &(towers.twr->tower),
2703                                            &res_binding);
2704         if (!NT_STATUS_IS_OK(status)) {
2705                 goto done;
2706         }
2707
2708         /* are further checks here necessary? */
2709         if (res_binding->transport != NCACN_IP_TCP) {
2710                 status = NT_STATUS_UNSUCCESSFUL;
2711                 goto done;
2712         }
2713
2714         *pport = (uint16_t)atoi(res_binding->endpoint);
2715
2716 done:
2717         TALLOC_FREE(tmp_ctx);
2718         return status;
2719 }
2720
2721 /**
2722  * Create a rpc pipe client struct, connecting to a host via tcp.
2723  * The port is determined by asking the endpoint mapper on the given
2724  * host.
2725  */
2726 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2727                            const struct sockaddr_storage *addr,
2728                            const struct ndr_interface_table *table,
2729                            struct rpc_pipe_client **presult)
2730 {
2731         NTSTATUS status;
2732         uint16_t port = 0;
2733
2734         status = rpc_pipe_get_tcp_port(host, addr, table, &port);
2735         if (!NT_STATUS_IS_OK(status)) {
2736                 return status;
2737         }
2738
2739         return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2740                                       table, presult);
2741 }
2742
2743 /********************************************************************
2744  Create a rpc pipe client struct, connecting to a unix domain socket
2745  ********************************************************************/
2746 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2747                                const struct ndr_interface_table *table,
2748                                struct rpc_pipe_client **presult)
2749 {
2750         struct rpc_pipe_client *result;
2751         struct sockaddr_un addr;
2752         NTSTATUS status;
2753         int fd;
2754         socklen_t salen;
2755
2756         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2757         if (result == NULL) {
2758                 return NT_STATUS_NO_MEMORY;
2759         }
2760
2761         result->abstract_syntax = table->syntax_id;
2762         result->transfer_syntax = ndr_transfer_syntax_ndr;
2763
2764         result->desthost = get_myname(result);
2765         result->srv_name_slash = talloc_asprintf_strupper_m(
2766                 result, "\\\\%s", result->desthost);
2767         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2768                 status = NT_STATUS_NO_MEMORY;
2769                 goto fail;
2770         }
2771
2772         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2773         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2774
2775         fd = socket(AF_UNIX, SOCK_STREAM, 0);
2776         if (fd == -1) {
2777                 status = map_nt_error_from_unix(errno);
2778                 goto fail;
2779         }
2780
2781         ZERO_STRUCT(addr);
2782         addr.sun_family = AF_UNIX;
2783         strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2784         salen = sizeof(struct sockaddr_un);
2785
2786         if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
2787                 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2788                           strerror(errno)));
2789                 close(fd);
2790                 return map_nt_error_from_unix(errno);
2791         }
2792
2793         status = rpc_transport_sock_init(result, fd, &result->transport);
2794         if (!NT_STATUS_IS_OK(status)) {
2795                 close(fd);
2796                 goto fail;
2797         }
2798
2799         result->transport->transport = NCALRPC;
2800
2801         result->assoc = dcerpc_association_create(result, 0);
2802         result->conn = dcerpc_connection_create(result, result->assoc,
2803                                                 &result->transport->stream);
2804         result->pres = dcerpc_presentation_allocate(result, result->conn, table,
2805                                                     &ndr_transfer_syntax_ndr);
2806         result->sec = dcerpc_security_allocate(result, result->conn,
2807                                                DCERPC_AUTH_TYPE_NONE,
2808                                                DCERPC_AUTH_LEVEL_NONE,
2809                                                NULL);
2810
2811         result->binding_handle = rpccli_bh_create(result, NULL, table);
2812         if (result->binding_handle == NULL) {
2813                 TALLOC_FREE(result);
2814                 return NT_STATUS_NO_MEMORY;
2815         }
2816
2817         *presult = result;
2818         return NT_STATUS_OK;
2819
2820  fail:
2821         TALLOC_FREE(result);
2822         return status;
2823 }
2824
2825 struct rpc_pipe_client_np_ref {
2826         struct cli_state *cli;
2827         struct rpc_pipe_client *pipe;
2828 };
2829
2830 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2831 {
2832         DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2833         return 0;
2834 }
2835
2836 /****************************************************************************
2837  Open a named pipe over SMB to a remote server.
2838  *
2839  * CAVEAT CALLER OF THIS FUNCTION:
2840  *    The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2841  *    so be sure that this function is called AFTER any structure (vs pointer)
2842  *    assignment of the cli.  In particular, libsmbclient does structure
2843  *    assignments of cli, which invalidates the data in the returned
2844  *    rpc_pipe_client if this function is called before the structure assignment
2845  *    of cli.
2846  * 
2847  ****************************************************************************/
2848
2849 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2850                                  const struct ndr_interface_table *table,
2851                                  struct rpc_pipe_client **presult)
2852 {
2853         struct rpc_pipe_client *result;
2854         NTSTATUS status;
2855         struct rpc_pipe_client_np_ref *np_ref;
2856
2857         /* sanity check to protect against crashes */
2858
2859         if ( !cli ) {
2860                 return NT_STATUS_INVALID_HANDLE;
2861         }
2862
2863         result = talloc_zero(NULL, struct rpc_pipe_client);
2864         if (result == NULL) {
2865                 return NT_STATUS_NO_MEMORY;
2866         }
2867
2868         result->abstract_syntax = table->syntax_id;
2869         result->transfer_syntax = ndr_transfer_syntax_ndr;
2870         result->desthost = talloc_strdup(result, smbXcli_conn_remote_name(cli->conn));
2871         result->srv_name_slash = talloc_asprintf_strupper_m(
2872                 result, "\\\\%s", result->desthost);
2873
2874         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2875         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2876
2877         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2878                 TALLOC_FREE(result);
2879                 return NT_STATUS_NO_MEMORY;
2880         }
2881
2882         status = rpc_transport_np_init(result, cli, table,
2883                                        &result->transport);
2884         if (!NT_STATUS_IS_OK(status)) {
2885                 TALLOC_FREE(result);
2886                 return status;
2887         }
2888
2889         result->transport->transport = NCACN_NP;
2890
2891         result->assoc = dcerpc_association_create(result, 0);
2892         result->conn = dcerpc_connection_create(result, result->assoc,
2893                                                 &result->transport->stream);
2894         dcerpc_connection_set_use_trans_fn(result->conn,
2895                                            tstream_smbXcli_np_use_trans);
2896         result->pres = dcerpc_presentation_allocate(result, result->conn, table,
2897                                                     &ndr_transfer_syntax_ndr);
2898         result->sec = dcerpc_security_allocate(result, result->conn,
2899                                                DCERPC_AUTH_TYPE_NONE,
2900                                                DCERPC_AUTH_LEVEL_NONE,
2901                                                NULL);
2902
2903         np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
2904         if (np_ref == NULL) {
2905                 TALLOC_FREE(result);
2906                 return NT_STATUS_NO_MEMORY;
2907         }
2908         np_ref->cli = cli;
2909         np_ref->pipe = result;
2910
2911         DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
2912         talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
2913
2914         result->binding_handle = rpccli_bh_create(result, NULL, table);
2915         if (result->binding_handle == NULL) {
2916                 TALLOC_FREE(result);
2917                 return NT_STATUS_NO_MEMORY;
2918         }
2919
2920         *presult = result;
2921         return NT_STATUS_OK;
2922 }
2923
2924 /****************************************************************************
2925  Open a pipe to a remote server.
2926  ****************************************************************************/
2927
2928 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2929                                   enum dcerpc_transport_t transport,
2930                                   const struct ndr_interface_table *table,
2931                                   struct rpc_pipe_client **presult)
2932 {
2933         switch (transport) {
2934         case NCACN_IP_TCP:
2935                 return rpc_pipe_open_tcp(NULL,
2936                                          smbXcli_conn_remote_name(cli->conn),
2937                                          smbXcli_conn_remote_sockaddr(cli->conn),
2938                                          table, presult);
2939         case NCACN_NP:
2940                 return rpc_pipe_open_np(cli, table, presult);
2941         default:
2942                 return NT_STATUS_NOT_IMPLEMENTED;
2943         }
2944 }
2945
2946 /****************************************************************************
2947  Open a named pipe to an SMB server and bind anonymously.
2948  ****************************************************************************/
2949
2950 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
2951                                             enum dcerpc_transport_t transport,
2952                                             const struct ndr_interface_table *table,
2953                                             struct rpc_pipe_client **presult)
2954 {
2955         struct rpc_pipe_client *result;
2956         struct pipe_auth_data *auth;
2957         NTSTATUS status;
2958
2959         status = cli_rpc_pipe_open(cli, transport, table, &result);
2960         if (!NT_STATUS_IS_OK(status)) {
2961                 return status;
2962         }
2963
2964         status = rpccli_anon_bind_data(result, &auth);
2965         if (!NT_STATUS_IS_OK(status)) {
2966                 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
2967                           nt_errstr(status)));
2968                 TALLOC_FREE(result);
2969                 return status;
2970         }
2971
2972         /*
2973          * This is a bit of an abstraction violation due to the fact that an
2974          * anonymous bind on an authenticated SMB inherits the user/domain
2975          * from the enclosing SMB creds
2976          */
2977
2978         TALLOC_FREE(auth->user_name);
2979         TALLOC_FREE(auth->domain);
2980
2981         auth->user_name = talloc_strdup(auth, cli->user_name);
2982         auth->domain = talloc_strdup(auth, cli->domain);
2983
2984         if (transport == NCACN_NP) {
2985                 struct smbXcli_session *session;
2986
2987                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2988                         session = cli->smb2.session;
2989                 } else {
2990                         session = cli->smb1.session;
2991                 }
2992
2993                 status = smbXcli_session_application_key(session, auth,
2994                                                 &auth->transport_session_key);
2995                 if (!NT_STATUS_IS_OK(status)) {
2996                         auth->transport_session_key = data_blob_null;
2997                 }
2998         }
2999
3000         if ((auth->user_name == NULL) || (auth->domain == NULL)) {
3001                 TALLOC_FREE(result);
3002                 return NT_STATUS_NO_MEMORY;
3003         }
3004
3005         status = rpc_pipe_bind(result, auth);
3006         if (!NT_STATUS_IS_OK(status)) {
3007                 int lvl = 0;
3008                 if (ndr_syntax_id_equal(&table->syntax_id,
3009                                         &ndr_table_dssetup.syntax_id)) {
3010                         /* non AD domains just don't have this pipe, avoid
3011                          * level 0 statement in that case - gd */
3012                         lvl = 3;
3013                 }
3014                 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3015                             "%s failed with error %s\n",
3016                             table->name,
3017                             nt_errstr(status) ));
3018                 TALLOC_FREE(result);
3019                 return status;
3020         }
3021
3022         DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3023                   "%s and bound anonymously.\n",
3024                   table->name,
3025                   result->desthost));
3026
3027         *presult = result;
3028         return NT_STATUS_OK;
3029 }
3030
3031 /****************************************************************************
3032  ****************************************************************************/
3033
3034 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3035                                   const struct ndr_interface_table *table,
3036                                   struct rpc_pipe_client **presult)
3037 {
3038         return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3039                                                   table, presult);
3040 }
3041
3042 /****************************************************************************
3043  Open a named pipe to an SMB server and bind using the mech specified
3044  ****************************************************************************/
3045
3046 NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
3047                                         const struct ndr_interface_table *table,
3048                                         enum dcerpc_transport_t transport,
3049                                         enum dcerpc_AuthType auth_type,
3050                                         enum dcerpc_AuthLevel auth_level,
3051                                         const char *server,
3052                                         const char *domain,
3053                                         const char *username,
3054                                         const char *password,
3055                                         struct rpc_pipe_client **presult)
3056 {
3057         struct rpc_pipe_client *result;
3058         struct pipe_auth_data *auth = NULL;
3059         const char *target_service = table->authservices->names[0];
3060         
3061         NTSTATUS status;
3062
3063         status = cli_rpc_pipe_open(cli, transport, table, &result);
3064         if (!NT_STATUS_IS_OK(status)) {
3065                 return status;
3066         }
3067
3068         status = rpccli_generic_bind_data(result,
3069                                           auth_type, auth_level,
3070                                           server, target_service,
3071                                           domain, username, password, 
3072                                           CRED_AUTO_USE_KERBEROS,
3073                                           NULL,
3074                                           &auth);
3075         if (!NT_STATUS_IS_OK(status)) {
3076                 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3077                           nt_errstr(status)));
3078                 goto err;
3079         }
3080
3081         status = rpc_pipe_bind(result, auth);
3082         if (!NT_STATUS_IS_OK(status)) {
3083                 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
3084                         nt_errstr(status) ));
3085                 goto err;
3086         }
3087
3088         DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
3089                 "machine %s and bound as user %s\\%s.\n", table->name,
3090                   result->desthost, domain, username));
3091
3092         *presult = result;
3093         return NT_STATUS_OK;
3094
3095   err:
3096
3097         TALLOC_FREE(result);
3098         return status;
3099 }
3100
3101 /****************************************************************************
3102  External interface.
3103  Open a named pipe to an SMB server and bind using schannel (bind type 68)
3104  using session_key. sign and seal.
3105
3106  The *pdc will be stolen onto this new pipe
3107  ****************************************************************************/
3108
3109 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3110                                              const struct ndr_interface_table *table,
3111                                              enum dcerpc_transport_t transport,
3112                                              const char *domain,
3113                                              struct netlogon_creds_cli_context *netlogon_creds,
3114                                              struct rpc_pipe_client **_rpccli)
3115 {
3116         struct rpc_pipe_client *rpccli;
3117         struct pipe_auth_data *rpcauth;
3118         struct netlogon_creds_CredentialState *creds = NULL;
3119         enum dcerpc_AuthLevel auth_level;
3120         NTSTATUS status;
3121         const char *target_service = table->authservices->names[0];
3122         int rpc_pipe_bind_dbglvl = 0;
3123
3124         status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
3125         if (!NT_STATUS_IS_OK(status)) {
3126                 return status;
3127         }
3128
3129         status = netlogon_creds_cli_lock(netlogon_creds, rpccli, &creds);
3130         if (!NT_STATUS_IS_OK(status)) {
3131                 DEBUG(0, ("netlogon_creds_cli_get returned %s\n",
3132                           nt_errstr(status)));
3133                 TALLOC_FREE(rpccli);
3134                 return status;
3135         }
3136
3137         auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
3138
3139         status = rpccli_generic_bind_data(rpccli,
3140                                           DCERPC_AUTH_TYPE_SCHANNEL,
3141                                           auth_level,
3142                                           NULL,
3143                                           target_service,
3144                                           domain,
3145                                           creds->computer_name,
3146                                           NULL,
3147                                           CRED_AUTO_USE_KERBEROS,
3148                                           creds,
3149                                           &rpcauth);
3150         if (!NT_STATUS_IS_OK(status)) {
3151                 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3152                           nt_errstr(status)));
3153                 TALLOC_FREE(rpccli);
3154                 return status;
3155         }
3156
3157         status = rpc_pipe_bind(rpccli, rpcauth);
3158         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3159                 rpc_pipe_bind_dbglvl = 1;
3160                 netlogon_creds_cli_delete(netlogon_creds, &creds);
3161         }
3162         if (!NT_STATUS_IS_OK(status)) {
3163                 DEBUG(rpc_pipe_bind_dbglvl,
3164                       ("cli_rpc_pipe_open_schannel_with_key: "
3165                        "rpc_pipe_bind failed with error %s\n",
3166                        nt_errstr(status)));
3167                 TALLOC_FREE(rpccli);
3168                 return status;
3169         }
3170
3171         TALLOC_FREE(creds);
3172
3173         if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) {
3174                 goto done;
3175         }
3176
3177         status = netlogon_creds_cli_check(netlogon_creds,
3178                                           rpccli->binding_handle);
3179         if (!NT_STATUS_IS_OK(status)) {
3180                 DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
3181                           nt_errstr(status)));
3182                 TALLOC_FREE(rpccli);
3183                 return status;
3184         }
3185
3186
3187 done:
3188         DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3189                   "for domain %s and bound using schannel.\n",
3190                   table->name,
3191                   rpccli->desthost, domain));
3192
3193         *_rpccli = rpccli;
3194         return NT_STATUS_OK;
3195 }
3196
3197 NTSTATUS cli_rpc_pipe_open_spnego(struct cli_state *cli,
3198                                   const struct ndr_interface_table *table,
3199                                   enum dcerpc_transport_t transport,
3200                                   const char *oid,
3201                                   enum dcerpc_AuthLevel auth_level,
3202                                   const char *server,
3203                                   const char *domain,
3204                                   const char *username,
3205                                   const char *password,
3206                                   struct rpc_pipe_client **presult)
3207 {
3208         struct rpc_pipe_client *result;
3209         struct pipe_auth_data *auth = NULL;
3210         const char *target_service = table->authservices->names[0];
3211         
3212         NTSTATUS status;
3213         enum credentials_use_kerberos use_kerberos;
3214
3215         if (strcmp(oid, GENSEC_OID_KERBEROS5) == 0) {
3216                 use_kerberos = CRED_MUST_USE_KERBEROS;
3217         } else if (strcmp(oid, GENSEC_OID_NTLMSSP) == 0) {
3218                 use_kerberos = CRED_DONT_USE_KERBEROS;
3219         } else {
3220                 return NT_STATUS_INVALID_PARAMETER;
3221         }
3222
3223         status = cli_rpc_pipe_open(cli, transport, table, &result);
3224         if (!NT_STATUS_IS_OK(status)) {
3225                 return status;
3226         }
3227
3228         status = rpccli_generic_bind_data(result,
3229                                           DCERPC_AUTH_TYPE_SPNEGO, auth_level,
3230                                           server, target_service,
3231                                           domain, username, password, 
3232                                           use_kerberos, NULL,
3233                                           &auth);
3234         if (!NT_STATUS_IS_OK(status)) {
3235                 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3236                           nt_errstr(status)));
3237                 goto err;
3238         }
3239
3240         status = rpc_pipe_bind(result, auth);
3241         if (!NT_STATUS_IS_OK(status)) {
3242                 DEBUG(0, ("cli_rpc_pipe_open_spnego: cli_rpc_pipe_bind failed with error %s\n",
3243                         nt_errstr(status) ));
3244                 goto err;
3245         }
3246
3247         DEBUG(10,("cli_rpc_pipe_open_spnego: opened pipe %s to "
3248                   "machine %s.\n", table->name,
3249                   result->desthost));
3250
3251         *presult = result;
3252         return NT_STATUS_OK;
3253
3254   err:
3255
3256         TALLOC_FREE(result);
3257         return status;
3258 }
3259
3260 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3261                              struct rpc_pipe_client *cli,
3262                              DATA_BLOB *session_key)
3263 {
3264         NTSTATUS status;
3265         struct pipe_auth_data *a;
3266         struct gensec_security *gensec_security;
3267         DATA_BLOB sk = data_blob_null;
3268         bool make_dup = false;
3269
3270         if (!session_key || !cli) {
3271                 return NT_STATUS_INVALID_PARAMETER;
3272         }
3273
3274         a = cli->auth;
3275
3276         if (a == NULL) {
3277                 return NT_STATUS_INVALID_PARAMETER;
3278         }
3279
3280         switch (cli->auth->auth_type) {
3281         case DCERPC_AUTH_TYPE_SPNEGO:
3282         case DCERPC_AUTH_TYPE_NTLMSSP:
3283         case DCERPC_AUTH_TYPE_KRB5:
3284                 gensec_security = talloc_get_type_abort(a->auth_ctx,
3285                                                 struct gensec_security);
3286                 status = gensec_session_key(gensec_security, mem_ctx, &sk);
3287                 if (!NT_STATUS_IS_OK(status)) {
3288                         return status;
3289                 }
3290                 make_dup = false;
3291                 break;
3292         case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
3293         case DCERPC_AUTH_TYPE_NONE:
3294                 sk = data_blob_const(a->transport_session_key.data,
3295                                      a->transport_session_key.length);
3296                 make_dup = true;
3297                 break;
3298         default:
3299                 break;
3300         }
3301
3302         if (!sk.data) {
3303                 return NT_STATUS_NO_USER_SESSION_KEY;
3304         }
3305
3306         if (make_dup) {
3307                 *session_key = data_blob_dup_talloc(mem_ctx, sk);
3308         } else {
3309                 *session_key = sk;
3310         }
3311
3312         return NT_STATUS_OK;
3313 }