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