rpc_client3: Fix a debug message
[samba.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         if (pkt->ptype == DCERPC_PKT_BIND_ACK) {
1956                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1957                         if (pauth->client_hdr_signing) {
1958                                 pauth->hdr_signing = true;
1959                         }
1960                 }
1961         }
1962
1963         state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1964
1965         switch(pauth->auth_type) {
1966
1967         case DCERPC_AUTH_TYPE_NONE:
1968                 /* Bind complete. */
1969                 tevent_req_done(req);
1970                 return;
1971
1972         default:
1973                 if (pkt->auth_length == 0) {
1974                         tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1975                         return;
1976                 }
1977
1978                 /* get auth credentials */
1979                 status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
1980                                                   &pkt->u.bind_ack.auth_info,
1981                                                   &auth, NULL, true);
1982                 if (!NT_STATUS_IS_OK(status)) {
1983                         DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1984                                   nt_errstr(status)));
1985                         tevent_req_nterror(req, status);
1986                         return;
1987                 }
1988
1989                 if (auth.auth_type != pauth->auth_type) {
1990                         DEBUG(0, (__location__ " Auth type %u mismatch expected %u.\n",
1991                                   auth.auth_type, pauth->auth_type));
1992                         tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1993                         return;
1994                 }
1995
1996                 if (auth.auth_level != pauth->auth_level) {
1997                         DEBUG(0, (__location__ " Auth level %u mismatch expected %u.\n",
1998                                   auth.auth_level, pauth->auth_level));
1999                         tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
2000                         return;
2001                 }
2002
2003                 if (auth.auth_context_id != pauth->auth_context_id) {
2004                         DEBUG(0, (__location__ " Auth context id %u mismatch expected %u.\n",
2005                                   (unsigned)auth.auth_context_id,
2006                                   (unsigned)pauth->auth_context_id));
2007                         tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
2008                         return;
2009                 }
2010
2011                 break;
2012         }
2013
2014         /*
2015          * For authenticated binds we may need to do 3 or 4 leg binds.
2016          */
2017
2018         switch(pauth->auth_type) {
2019
2020         case DCERPC_AUTH_TYPE_NONE:
2021                 /* Bind complete. */
2022                 tevent_req_done(req);
2023                 return;
2024
2025         default:
2026                 gensec_security = pauth->auth_ctx;
2027
2028
2029                 status = gensec_update(gensec_security, state,
2030                                        auth.credentials, &auth_token);
2031                 if (NT_STATUS_EQUAL(status,
2032                                     NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2033                         status = rpc_bind_next_send(req, state,
2034                                                         &auth_token);
2035                 } else if (NT_STATUS_IS_OK(status)) {
2036                         if (pauth->hdr_signing) {
2037                                 gensec_want_feature(gensec_security,
2038                                                     GENSEC_FEATURE_SIGN_PKT_HEADER);
2039                         }
2040
2041                         if (auth_token.length == 0) {
2042                                 /* Bind complete. */
2043                                 tevent_req_done(req);
2044                                 return;
2045                         }
2046                         status = rpc_bind_finish_send(req, state,
2047                                                         &auth_token);
2048                 }
2049                 break;
2050         }
2051
2052         if (!NT_STATUS_IS_OK(status)) {
2053                 tevent_req_nterror(req, status);
2054         }
2055         return;
2056 }
2057
2058 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
2059                                    struct rpc_pipe_bind_state *state,
2060                                    DATA_BLOB *auth_token)
2061 {
2062         struct pipe_auth_data *auth = state->cli->auth;
2063         struct tevent_req *subreq;
2064         NTSTATUS status;
2065
2066         /* Now prepare the alter context pdu. */
2067         data_blob_free(&state->rpc_out);
2068
2069         status = create_rpc_alter_context(state, auth,
2070                                           state->rpc_call_id,
2071                                           &state->cli->abstract_syntax,
2072                                           &state->cli->transfer_syntax,
2073                                           auth_token,
2074                                           &state->rpc_out);
2075         if (!NT_STATUS_IS_OK(status)) {
2076                 return status;
2077         }
2078
2079         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2080                                    &state->rpc_out, DCERPC_PKT_ALTER_RESP,
2081                                    state->rpc_call_id);
2082         if (subreq == NULL) {
2083                 return NT_STATUS_NO_MEMORY;
2084         }
2085         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2086         return NT_STATUS_OK;
2087 }
2088
2089 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
2090                                      struct rpc_pipe_bind_state *state,
2091                                      DATA_BLOB *auth_token)
2092 {
2093         struct pipe_auth_data *auth = state->cli->auth;
2094         struct tevent_req *subreq;
2095         NTSTATUS status;
2096
2097         state->auth3 = true;
2098
2099         /* Now prepare the auth3 context pdu. */
2100         data_blob_free(&state->rpc_out);
2101
2102         status = create_rpc_bind_auth3(state, state->cli, auth,
2103                                         state->rpc_call_id,
2104                                         auth_token,
2105                                         &state->rpc_out);
2106         if (!NT_STATUS_IS_OK(status)) {
2107                 return status;
2108         }
2109
2110         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2111                                    &state->rpc_out, DCERPC_PKT_AUTH3,
2112                                    state->rpc_call_id);
2113         if (subreq == NULL) {
2114                 return NT_STATUS_NO_MEMORY;
2115         }
2116         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2117         return NT_STATUS_OK;
2118 }
2119
2120 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2121 {
2122         return tevent_req_simple_recv_ntstatus(req);
2123 }
2124
2125 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2126                        struct pipe_auth_data *auth)
2127 {
2128         TALLOC_CTX *frame = talloc_stackframe();
2129         struct tevent_context *ev;
2130         struct tevent_req *req;
2131         NTSTATUS status = NT_STATUS_OK;
2132
2133         ev = samba_tevent_context_init(frame);
2134         if (ev == NULL) {
2135                 status = NT_STATUS_NO_MEMORY;
2136                 goto fail;
2137         }
2138
2139         req = rpc_pipe_bind_send(frame, ev, cli, auth);
2140         if (req == NULL) {
2141                 status = NT_STATUS_NO_MEMORY;
2142                 goto fail;
2143         }
2144
2145         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2146                 goto fail;
2147         }
2148
2149         status = rpc_pipe_bind_recv(req);
2150  fail:
2151         TALLOC_FREE(frame);
2152         return status;
2153 }
2154
2155 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2156
2157 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2158                                 unsigned int timeout)
2159 {
2160         unsigned int old;
2161
2162         if (rpc_cli->transport == NULL) {
2163                 return RPCCLI_DEFAULT_TIMEOUT;
2164         }
2165
2166         if (rpc_cli->transport->set_timeout == NULL) {
2167                 return RPCCLI_DEFAULT_TIMEOUT;
2168         }
2169
2170         old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2171         if (old == 0) {
2172                 return RPCCLI_DEFAULT_TIMEOUT;
2173         }
2174
2175         return old;
2176 }
2177
2178 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2179 {
2180         if (rpc_cli == NULL) {
2181                 return false;
2182         }
2183
2184         if (rpc_cli->transport == NULL) {
2185                 return false;
2186         }
2187
2188         return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2189 }
2190
2191 struct rpccli_bh_state {
2192         struct rpc_pipe_client *rpc_cli;
2193 };
2194
2195 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2196 {
2197         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2198                                      struct rpccli_bh_state);
2199
2200         return rpccli_is_connected(hs->rpc_cli);
2201 }
2202
2203 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2204                                       uint32_t timeout)
2205 {
2206         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2207                                      struct rpccli_bh_state);
2208
2209         return rpccli_set_timeout(hs->rpc_cli, timeout);
2210 }
2211
2212 static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
2213                                 enum dcerpc_AuthType *auth_type,
2214                                 enum dcerpc_AuthLevel *auth_level)
2215 {
2216         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2217                                      struct rpccli_bh_state);
2218
2219         if (hs->rpc_cli == NULL) {
2220                 return;
2221         }
2222
2223         if (hs->rpc_cli->auth == NULL) {
2224                 return;
2225         }
2226
2227         *auth_type = hs->rpc_cli->auth->auth_type;
2228         *auth_level = hs->rpc_cli->auth->auth_level;
2229 }
2230
2231 struct rpccli_bh_raw_call_state {
2232         DATA_BLOB in_data;
2233         DATA_BLOB out_data;
2234         uint32_t out_flags;
2235 };
2236
2237 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2238
2239 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2240                                                   struct tevent_context *ev,
2241                                                   struct dcerpc_binding_handle *h,
2242                                                   const struct GUID *object,
2243                                                   uint32_t opnum,
2244                                                   uint32_t in_flags,
2245                                                   const uint8_t *in_data,
2246                                                   size_t in_length)
2247 {
2248         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2249                                      struct rpccli_bh_state);
2250         struct tevent_req *req;
2251         struct rpccli_bh_raw_call_state *state;
2252         bool ok;
2253         struct tevent_req *subreq;
2254
2255         req = tevent_req_create(mem_ctx, &state,
2256                                 struct rpccli_bh_raw_call_state);
2257         if (req == NULL) {
2258                 return NULL;
2259         }
2260         state->in_data.data = discard_const_p(uint8_t, in_data);
2261         state->in_data.length = in_length;
2262
2263         ok = rpccli_bh_is_connected(h);
2264         if (!ok) {
2265                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2266                 return tevent_req_post(req, ev);
2267         }
2268
2269         subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2270                                        opnum, object, &state->in_data);
2271         if (tevent_req_nomem(subreq, req)) {
2272                 return tevent_req_post(req, ev);
2273         }
2274         tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2275
2276         return req;
2277 }
2278
2279 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2280 {
2281         struct tevent_req *req =
2282                 tevent_req_callback_data(subreq,
2283                 struct tevent_req);
2284         struct rpccli_bh_raw_call_state *state =
2285                 tevent_req_data(req,
2286                 struct rpccli_bh_raw_call_state);
2287         NTSTATUS status;
2288
2289         state->out_flags = 0;
2290
2291         /* TODO: support bigendian responses */
2292
2293         status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2294         TALLOC_FREE(subreq);
2295         if (!NT_STATUS_IS_OK(status)) {
2296                 tevent_req_nterror(req, status);
2297                 return;
2298         }
2299
2300         tevent_req_done(req);
2301 }
2302
2303 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2304                                         TALLOC_CTX *mem_ctx,
2305                                         uint8_t **out_data,
2306                                         size_t *out_length,
2307                                         uint32_t *out_flags)
2308 {
2309         struct rpccli_bh_raw_call_state *state =
2310                 tevent_req_data(req,
2311                 struct rpccli_bh_raw_call_state);
2312         NTSTATUS status;
2313
2314         if (tevent_req_is_nterror(req, &status)) {
2315                 tevent_req_received(req);
2316                 return status;
2317         }
2318
2319         *out_data = talloc_move(mem_ctx, &state->out_data.data);
2320         *out_length = state->out_data.length;
2321         *out_flags = state->out_flags;
2322         tevent_req_received(req);
2323         return NT_STATUS_OK;
2324 }
2325
2326 struct rpccli_bh_disconnect_state {
2327         uint8_t _dummy;
2328 };
2329
2330 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2331                                                 struct tevent_context *ev,
2332                                                 struct dcerpc_binding_handle *h)
2333 {
2334         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2335                                      struct rpccli_bh_state);
2336         struct tevent_req *req;
2337         struct rpccli_bh_disconnect_state *state;
2338         bool ok;
2339
2340         req = tevent_req_create(mem_ctx, &state,
2341                                 struct rpccli_bh_disconnect_state);
2342         if (req == NULL) {
2343                 return NULL;
2344         }
2345
2346         ok = rpccli_bh_is_connected(h);
2347         if (!ok) {
2348                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2349                 return tevent_req_post(req, ev);
2350         }
2351
2352         /*
2353          * TODO: do a real async disconnect ...
2354          *
2355          * For now we do it sync...
2356          */
2357         TALLOC_FREE(hs->rpc_cli->transport);
2358         hs->rpc_cli = NULL;
2359
2360         tevent_req_done(req);
2361         return tevent_req_post(req, ev);
2362 }
2363
2364 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2365 {
2366         NTSTATUS status;
2367
2368         if (tevent_req_is_nterror(req, &status)) {
2369                 tevent_req_received(req);
2370                 return status;
2371         }
2372
2373         tevent_req_received(req);
2374         return NT_STATUS_OK;
2375 }
2376
2377 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2378 {
2379         return true;
2380 }
2381
2382 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2383                                    int ndr_flags,
2384                                    const void *_struct_ptr,
2385                                    const struct ndr_interface_call *call)
2386 {
2387         void *struct_ptr = discard_const(_struct_ptr);
2388
2389         if (DEBUGLEVEL < 10) {
2390                 return;
2391         }
2392
2393         if (ndr_flags & NDR_IN) {
2394                 ndr_print_function_debug(call->ndr_print,
2395                                          call->name,
2396                                          ndr_flags,
2397                                          struct_ptr);
2398         }
2399         if (ndr_flags & NDR_OUT) {
2400                 ndr_print_function_debug(call->ndr_print,
2401                                          call->name,
2402                                          ndr_flags,
2403                                          struct_ptr);
2404         }
2405 }
2406
2407 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2408         .name                   = "rpccli",
2409         .is_connected           = rpccli_bh_is_connected,
2410         .set_timeout            = rpccli_bh_set_timeout,
2411         .auth_info              = rpccli_bh_auth_info,
2412         .raw_call_send          = rpccli_bh_raw_call_send,
2413         .raw_call_recv          = rpccli_bh_raw_call_recv,
2414         .disconnect_send        = rpccli_bh_disconnect_send,
2415         .disconnect_recv        = rpccli_bh_disconnect_recv,
2416
2417         .ref_alloc              = rpccli_bh_ref_alloc,
2418         .do_ndr_print           = rpccli_bh_do_ndr_print,
2419 };
2420
2421 /* initialise a rpc_pipe_client binding handle */
2422 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2423                                         const struct GUID *object,
2424                                         const struct ndr_interface_table *table)
2425 {
2426         struct dcerpc_binding_handle *h;
2427         struct rpccli_bh_state *hs;
2428
2429         h = dcerpc_binding_handle_create(c,
2430                                          &rpccli_bh_ops,
2431                                          object,
2432                                          table,
2433                                          &hs,
2434                                          struct rpccli_bh_state,
2435                                          __location__);
2436         if (h == NULL) {
2437                 return NULL;
2438         }
2439         hs->rpc_cli = c;
2440
2441         return h;
2442 }
2443
2444 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2445                                struct pipe_auth_data **presult)
2446 {
2447         struct pipe_auth_data *result;
2448         struct auth_generic_state *auth_generic_ctx;
2449         NTSTATUS status;
2450
2451         result = talloc_zero(mem_ctx, struct pipe_auth_data);
2452         if (result == NULL) {
2453                 return NT_STATUS_NO_MEMORY;
2454         }
2455
2456         result->auth_type = DCERPC_AUTH_TYPE_NONE;
2457         result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2458         result->auth_context_id = 0;
2459
2460         status = auth_generic_client_prepare(result,
2461                                              &auth_generic_ctx);
2462         if (!NT_STATUS_IS_OK(status)) {
2463                 DEBUG(1, ("Failed to create auth_generic context: %s\n",
2464                           nt_errstr(status)));
2465         }
2466
2467         status = auth_generic_set_username(auth_generic_ctx, "");
2468         if (!NT_STATUS_IS_OK(status)) {
2469                 DEBUG(1, ("Failed to set username: %s\n",
2470                           nt_errstr(status)));
2471         }
2472
2473         status = auth_generic_set_domain(auth_generic_ctx, "");
2474         if (!NT_STATUS_IS_OK(status)) {
2475                 DEBUG(1, ("Failed to set domain: %s\n",
2476                           nt_errstr(status)));
2477                 return status;
2478         }
2479
2480         status = gensec_set_credentials(auth_generic_ctx->gensec_security,
2481                                         auth_generic_ctx->credentials);
2482         if (!NT_STATUS_IS_OK(status)) {
2483                 DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
2484                           nt_errstr(status)));
2485                 return status;
2486         }
2487         talloc_unlink(auth_generic_ctx, auth_generic_ctx->credentials);
2488         auth_generic_ctx->credentials = NULL;
2489
2490         result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2491         talloc_free(auth_generic_ctx);
2492         *presult = result;
2493         return NT_STATUS_OK;
2494 }
2495
2496 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2497                                          enum dcerpc_AuthType auth_type,
2498                                          enum dcerpc_AuthLevel auth_level,
2499                                          const char *server,
2500                                          const char *target_service,
2501                                          const char *domain,
2502                                          const char *username,
2503                                          const char *password,
2504                                          enum credentials_use_kerberos use_kerberos,
2505                                          struct netlogon_creds_CredentialState *creds,
2506                                          struct pipe_auth_data **presult)
2507 {
2508         struct auth_generic_state *auth_generic_ctx;
2509         struct pipe_auth_data *result;
2510         NTSTATUS status;
2511
2512         result = talloc_zero(mem_ctx, struct pipe_auth_data);
2513         if (result == NULL) {
2514                 return NT_STATUS_NO_MEMORY;
2515         }
2516
2517         result->auth_type = auth_type;
2518         result->auth_level = auth_level;
2519         result->auth_context_id = 1;
2520
2521         status = auth_generic_client_prepare(result,
2522                                              &auth_generic_ctx);
2523         if (!NT_STATUS_IS_OK(status)) {
2524                 goto fail;
2525         }
2526
2527         status = auth_generic_set_username(auth_generic_ctx, username);
2528         if (!NT_STATUS_IS_OK(status)) {
2529                 goto fail;
2530         }
2531
2532         status = auth_generic_set_domain(auth_generic_ctx, domain);
2533         if (!NT_STATUS_IS_OK(status)) {
2534                 goto fail;
2535         }
2536
2537         status = auth_generic_set_password(auth_generic_ctx, password);
2538         if (!NT_STATUS_IS_OK(status)) {
2539                 goto fail;
2540         }
2541
2542         status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2543         if (!NT_STATUS_IS_OK(status)) {
2544                 goto fail;
2545         }
2546
2547         status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2548         if (!NT_STATUS_IS_OK(status)) {
2549                 goto fail;
2550         }
2551
2552         cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos);
2553         cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
2554
2555         status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2556         if (!NT_STATUS_IS_OK(status)) {
2557                 goto fail;
2558         }
2559
2560         result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2561         talloc_free(auth_generic_ctx);
2562         *presult = result;
2563         return NT_STATUS_OK;
2564
2565  fail:
2566         TALLOC_FREE(result);
2567         return status;
2568 }
2569
2570 /* This routine steals the creds pointer that is passed in */
2571 static NTSTATUS rpccli_generic_bind_data_from_creds(TALLOC_CTX *mem_ctx,
2572                                                     enum dcerpc_AuthType auth_type,
2573                                                     enum dcerpc_AuthLevel auth_level,
2574                                                     const char *server,
2575                                                     const char *target_service,
2576                                                     struct cli_credentials *creds,
2577                                                     struct pipe_auth_data **presult)
2578 {
2579         struct auth_generic_state *auth_generic_ctx;
2580         struct pipe_auth_data *result;
2581         NTSTATUS status;
2582
2583         result = talloc_zero(mem_ctx, struct pipe_auth_data);
2584         if (result == NULL) {
2585                 return NT_STATUS_NO_MEMORY;
2586         }
2587
2588         result->auth_type = auth_type;
2589         result->auth_level = auth_level;
2590         result->auth_context_id = 1;
2591
2592         status = auth_generic_client_prepare(result,
2593                                              &auth_generic_ctx);
2594         if (!NT_STATUS_IS_OK(status)) {
2595                 goto fail;
2596         }
2597
2598         status = auth_generic_set_creds(auth_generic_ctx, creds);
2599         if (!NT_STATUS_IS_OK(status)) {
2600                 goto fail;
2601         }
2602
2603         status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2604         if (!NT_STATUS_IS_OK(status)) {
2605                 goto fail;
2606         }
2607
2608         status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2609         if (!NT_STATUS_IS_OK(status)) {
2610                 goto fail;
2611         }
2612
2613         status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2614         if (!NT_STATUS_IS_OK(status)) {
2615                 goto fail;
2616         }
2617
2618         result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2619         talloc_free(auth_generic_ctx);
2620         *presult = result;
2621         return NT_STATUS_OK;
2622
2623  fail:
2624         TALLOC_FREE(result);
2625         return status;
2626 }
2627
2628 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2629                                   struct pipe_auth_data **presult)
2630 {
2631         return rpccli_generic_bind_data(mem_ctx,
2632                                         DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
2633                                         DCERPC_AUTH_LEVEL_CONNECT,
2634                                         NULL, /* server */
2635                                         "host", /* target_service */
2636                                         NAME_NT_AUTHORITY, /* domain */
2637                                         "SYSTEM",
2638                                         NULL, /* password */
2639                                         CRED_DONT_USE_KERBEROS,
2640                                         NULL, /* netlogon_creds_CredentialState */
2641                                         presult);
2642 }
2643
2644 /**
2645  * Create an rpc pipe client struct, connecting to a tcp port.
2646  */
2647 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2648                                        const struct sockaddr_storage *ss_addr,
2649                                        uint16_t port,
2650                                        const struct ndr_interface_table *table,
2651                                        struct rpc_pipe_client **presult)
2652 {
2653         struct rpc_pipe_client *result;
2654         struct sockaddr_storage addr;
2655         NTSTATUS status;
2656         int fd;
2657
2658         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2659         if (result == NULL) {
2660                 return NT_STATUS_NO_MEMORY;
2661         }
2662
2663         result->abstract_syntax = table->syntax_id;
2664         result->transfer_syntax = ndr_transfer_syntax_ndr;
2665
2666         result->desthost = talloc_strdup(result, host);
2667         result->srv_name_slash = talloc_asprintf_strupper_m(
2668                 result, "\\\\%s", result->desthost);
2669         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2670                 status = NT_STATUS_NO_MEMORY;
2671                 goto fail;
2672         }
2673
2674         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2675
2676         if (ss_addr == NULL) {
2677                 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2678                         status = NT_STATUS_NOT_FOUND;
2679                         goto fail;
2680                 }
2681         } else {
2682                 addr = *ss_addr;
2683         }
2684
2685         status = open_socket_out(&addr, port, 60*1000, &fd);
2686         if (!NT_STATUS_IS_OK(status)) {
2687                 goto fail;
2688         }
2689         set_socket_options(fd, lp_socket_options());
2690
2691         status = rpc_transport_sock_init(result, fd, &result->transport);
2692         if (!NT_STATUS_IS_OK(status)) {
2693                 close(fd);
2694                 goto fail;
2695         }
2696
2697         result->transport->transport = NCACN_IP_TCP;
2698
2699         result->binding_handle = rpccli_bh_create(result, NULL, table);
2700         if (result->binding_handle == NULL) {
2701                 TALLOC_FREE(result);
2702                 return NT_STATUS_NO_MEMORY;
2703         }
2704
2705         *presult = result;
2706         return NT_STATUS_OK;
2707
2708  fail:
2709         TALLOC_FREE(result);
2710         return status;
2711 }
2712
2713 /**
2714  * Determine the tcp port on which a dcerpc interface is listening
2715  * for the ncacn_ip_tcp transport via the endpoint mapper of the
2716  * target host.
2717  */
2718 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2719                                       const struct sockaddr_storage *addr,
2720                                       const struct ndr_interface_table *table,
2721                                       uint16_t *pport)
2722 {
2723         NTSTATUS status;
2724         struct rpc_pipe_client *epm_pipe = NULL;
2725         struct dcerpc_binding_handle *epm_handle = NULL;
2726         struct pipe_auth_data *auth = NULL;
2727         struct dcerpc_binding *map_binding = NULL;
2728         struct dcerpc_binding *res_binding = NULL;
2729         enum dcerpc_transport_t transport;
2730         const char *endpoint = NULL;
2731         struct epm_twr_t *map_tower = NULL;
2732         struct epm_twr_t *res_towers = NULL;
2733         struct policy_handle *entry_handle = NULL;
2734         uint32_t num_towers = 0;
2735         uint32_t max_towers = 1;
2736         struct epm_twr_p_t towers;
2737         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2738         uint32_t result = 0;
2739
2740         if (pport == NULL) {
2741                 status = NT_STATUS_INVALID_PARAMETER;
2742                 goto done;
2743         }
2744
2745         if (ndr_syntax_id_equal(&table->syntax_id,
2746                                 &ndr_table_epmapper.syntax_id)) {
2747                 *pport = 135;
2748                 status = NT_STATUS_OK;
2749                 goto done;
2750         }
2751
2752         /* open the connection to the endpoint mapper */
2753         status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2754                                         &ndr_table_epmapper,
2755                                         &epm_pipe);
2756
2757         if (!NT_STATUS_IS_OK(status)) {
2758                 goto done;
2759         }
2760         epm_handle = epm_pipe->binding_handle;
2761
2762         status = rpccli_anon_bind_data(tmp_ctx, &auth);
2763         if (!NT_STATUS_IS_OK(status)) {
2764                 goto done;
2765         }
2766
2767         status = rpc_pipe_bind(epm_pipe, auth);
2768         if (!NT_STATUS_IS_OK(status)) {
2769                 goto done;
2770         }
2771
2772         /* create tower for asking the epmapper */
2773
2774         status = dcerpc_parse_binding(tmp_ctx, "ncacn_ip_tcp:[135]",
2775                                       &map_binding);
2776         if (!NT_STATUS_IS_OK(status)) {
2777                 goto done;
2778         }
2779
2780         status = dcerpc_binding_set_abstract_syntax(map_binding,
2781                                                     &table->syntax_id);
2782         if (!NT_STATUS_IS_OK(status)) {
2783                 goto done;
2784         }
2785
2786         map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
2787         if (map_tower == NULL) {
2788                 status = NT_STATUS_NO_MEMORY;
2789                 goto done;
2790         }
2791
2792         status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2793                                             &(map_tower->tower));
2794         if (!NT_STATUS_IS_OK(status)) {
2795                 goto done;
2796         }
2797
2798         /* allocate further parameters for the epm_Map call */
2799
2800         res_towers = talloc_array(tmp_ctx, struct epm_twr_t, max_towers);
2801         if (res_towers == NULL) {
2802                 status = NT_STATUS_NO_MEMORY;
2803                 goto done;
2804         }
2805         towers.twr = res_towers;
2806
2807         entry_handle = talloc_zero(tmp_ctx, struct policy_handle);
2808         if (entry_handle == NULL) {
2809                 status = NT_STATUS_NO_MEMORY;
2810                 goto done;
2811         }
2812
2813         /* ask the endpoint mapper for the port */
2814
2815         status = dcerpc_epm_Map(epm_handle,
2816                                 tmp_ctx,
2817                                 discard_const_p(struct GUID,
2818                                               &(table->syntax_id.uuid)),
2819                                 map_tower,
2820                                 entry_handle,
2821                                 max_towers,
2822                                 &num_towers,
2823                                 &towers,
2824                                 &result);
2825
2826         if (!NT_STATUS_IS_OK(status)) {
2827                 goto done;
2828         }
2829
2830         if (result != EPMAPPER_STATUS_OK) {
2831                 status = NT_STATUS_UNSUCCESSFUL;
2832                 goto done;
2833         }
2834
2835         if (num_towers != 1) {
2836                 status = NT_STATUS_UNSUCCESSFUL;
2837                 goto done;
2838         }
2839
2840         /* extract the port from the answer */
2841
2842         status = dcerpc_binding_from_tower(tmp_ctx,
2843                                            &(towers.twr->tower),
2844                                            &res_binding);
2845         if (!NT_STATUS_IS_OK(status)) {
2846                 goto done;
2847         }
2848
2849         transport = dcerpc_binding_get_transport(res_binding);
2850         endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
2851
2852         /* are further checks here necessary? */
2853         if (transport != NCACN_IP_TCP) {
2854                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2855                 goto done;
2856         }
2857
2858         if (endpoint == NULL) {
2859                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2860                 goto done;
2861         }
2862
2863         *pport = (uint16_t)atoi(endpoint);
2864
2865 done:
2866         TALLOC_FREE(tmp_ctx);
2867         return status;
2868 }
2869
2870 /**
2871  * Create a rpc pipe client struct, connecting to a host via tcp.
2872  * The port is determined by asking the endpoint mapper on the given
2873  * host.
2874  */
2875 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2876                            const struct sockaddr_storage *addr,
2877                            const struct ndr_interface_table *table,
2878                            struct rpc_pipe_client **presult)
2879 {
2880         NTSTATUS status;
2881         uint16_t port = 0;
2882
2883         status = rpc_pipe_get_tcp_port(host, addr, table, &port);
2884         if (!NT_STATUS_IS_OK(status)) {
2885                 return status;
2886         }
2887
2888         return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2889                                       table, presult);
2890 }
2891
2892 /********************************************************************
2893  Create a rpc pipe client struct, connecting to a unix domain socket
2894  ********************************************************************/
2895 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2896                                const struct ndr_interface_table *table,
2897                                struct rpc_pipe_client **presult)
2898 {
2899         struct rpc_pipe_client *result;
2900         struct sockaddr_un addr;
2901         NTSTATUS status;
2902         int fd;
2903         socklen_t salen;
2904
2905         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2906         if (result == NULL) {
2907                 return NT_STATUS_NO_MEMORY;
2908         }
2909
2910         result->abstract_syntax = table->syntax_id;
2911         result->transfer_syntax = ndr_transfer_syntax_ndr;
2912
2913         result->desthost = get_myname(result);
2914         result->srv_name_slash = talloc_asprintf_strupper_m(
2915                 result, "\\\\%s", result->desthost);
2916         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2917                 status = NT_STATUS_NO_MEMORY;
2918                 goto fail;
2919         }
2920
2921         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2922
2923         fd = socket(AF_UNIX, SOCK_STREAM, 0);
2924         if (fd == -1) {
2925                 status = map_nt_error_from_unix(errno);
2926                 goto fail;
2927         }
2928
2929         ZERO_STRUCT(addr);
2930         addr.sun_family = AF_UNIX;
2931         strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2932         salen = sizeof(struct sockaddr_un);
2933
2934         if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
2935                 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2936                           strerror(errno)));
2937                 close(fd);
2938                 return map_nt_error_from_unix(errno);
2939         }
2940
2941         status = rpc_transport_sock_init(result, fd, &result->transport);
2942         if (!NT_STATUS_IS_OK(status)) {
2943                 close(fd);
2944                 goto fail;
2945         }
2946
2947         result->transport->transport = NCALRPC;
2948
2949         result->binding_handle = rpccli_bh_create(result, NULL, table);
2950         if (result->binding_handle == NULL) {
2951                 TALLOC_FREE(result);
2952                 return NT_STATUS_NO_MEMORY;
2953         }
2954
2955         *presult = result;
2956         return NT_STATUS_OK;
2957
2958  fail:
2959         TALLOC_FREE(result);
2960         return status;
2961 }
2962
2963 struct rpc_pipe_client_np_ref {
2964         struct cli_state *cli;
2965         struct rpc_pipe_client *pipe;
2966 };
2967
2968 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2969 {
2970         DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2971         return 0;
2972 }
2973
2974 /****************************************************************************
2975  Open a named pipe over SMB to a remote server.
2976  *
2977  * CAVEAT CALLER OF THIS FUNCTION:
2978  *    The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2979  *    so be sure that this function is called AFTER any structure (vs pointer)
2980  *    assignment of the cli.  In particular, libsmbclient does structure
2981  *    assignments of cli, which invalidates the data in the returned
2982  *    rpc_pipe_client if this function is called before the structure assignment
2983  *    of cli.
2984  * 
2985  ****************************************************************************/
2986
2987 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2988                                  const struct ndr_interface_table *table,
2989                                  struct rpc_pipe_client **presult)
2990 {
2991         struct rpc_pipe_client *result;
2992         NTSTATUS status;
2993         struct rpc_pipe_client_np_ref *np_ref;
2994
2995         /* sanity check to protect against crashes */
2996
2997         if ( !cli ) {
2998                 return NT_STATUS_INVALID_HANDLE;
2999         }
3000
3001         result = talloc_zero(NULL, struct rpc_pipe_client);
3002         if (result == NULL) {
3003                 return NT_STATUS_NO_MEMORY;
3004         }
3005
3006         result->abstract_syntax = table->syntax_id;
3007         result->transfer_syntax = ndr_transfer_syntax_ndr;
3008         result->desthost = talloc_strdup(result, smbXcli_conn_remote_name(cli->conn));
3009         result->srv_name_slash = talloc_asprintf_strupper_m(
3010                 result, "\\\\%s", result->desthost);
3011
3012         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3013
3014         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3015                 TALLOC_FREE(result);
3016                 return NT_STATUS_NO_MEMORY;
3017         }
3018
3019         status = rpc_transport_np_init(result, cli, table,
3020                                        &result->transport);
3021         if (!NT_STATUS_IS_OK(status)) {
3022                 TALLOC_FREE(result);
3023                 return status;
3024         }
3025
3026         result->transport->transport = NCACN_NP;
3027
3028         np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3029         if (np_ref == NULL) {
3030                 TALLOC_FREE(result);
3031                 return NT_STATUS_NO_MEMORY;
3032         }
3033         np_ref->cli = cli;
3034         np_ref->pipe = result;
3035
3036         DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3037         talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3038
3039         result->binding_handle = rpccli_bh_create(result, NULL, table);
3040         if (result->binding_handle == NULL) {
3041                 TALLOC_FREE(result);
3042                 return NT_STATUS_NO_MEMORY;
3043         }
3044
3045         *presult = result;
3046         return NT_STATUS_OK;
3047 }
3048
3049 /****************************************************************************
3050  Open a pipe to a remote server.
3051  ****************************************************************************/
3052
3053 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3054                                   enum dcerpc_transport_t transport,
3055                                   const struct ndr_interface_table *table,
3056                                   struct rpc_pipe_client **presult)
3057 {
3058         switch (transport) {
3059         case NCACN_IP_TCP:
3060                 return rpc_pipe_open_tcp(NULL,
3061                                          smbXcli_conn_remote_name(cli->conn),
3062                                          smbXcli_conn_remote_sockaddr(cli->conn),
3063                                          table, presult);
3064         case NCACN_NP:
3065                 return rpc_pipe_open_np(cli, table, presult);
3066         default:
3067                 return NT_STATUS_NOT_IMPLEMENTED;
3068         }
3069 }
3070
3071 /****************************************************************************
3072  Open a named pipe to an SMB server and bind anonymously.
3073  ****************************************************************************/
3074
3075 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3076                                             enum dcerpc_transport_t transport,
3077                                             const struct ndr_interface_table *table,
3078                                             struct rpc_pipe_client **presult)
3079 {
3080         struct rpc_pipe_client *result;
3081         struct pipe_auth_data *auth;
3082         NTSTATUS status;
3083
3084         status = cli_rpc_pipe_open(cli, transport, table, &result);
3085         if (!NT_STATUS_IS_OK(status)) {
3086                 return status;
3087         }
3088
3089         status = rpccli_anon_bind_data(result, &auth);
3090         if (!NT_STATUS_IS_OK(status)) {
3091                 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3092                           nt_errstr(status)));
3093                 TALLOC_FREE(result);
3094                 return status;
3095         }
3096
3097         /*
3098          * This is a bit of an abstraction violation due to the fact that an
3099          * anonymous bind on an authenticated SMB inherits the user/domain
3100          * from the enclosing SMB creds
3101          */
3102
3103         if (transport == NCACN_NP) {
3104                 struct smbXcli_session *session;
3105
3106                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3107                         session = cli->smb2.session;
3108                 } else {
3109                         session = cli->smb1.session;
3110                 }
3111
3112                 status = smbXcli_session_application_key(session, auth,
3113                                                 &auth->transport_session_key);
3114                 if (!NT_STATUS_IS_OK(status)) {
3115                         auth->transport_session_key = data_blob_null;
3116                 }
3117         }
3118
3119         status = rpc_pipe_bind(result, auth);
3120         if (!NT_STATUS_IS_OK(status)) {
3121                 int lvl = 0;
3122                 if (ndr_syntax_id_equal(&table->syntax_id,
3123                                         &ndr_table_dssetup.syntax_id)) {
3124                         /* non AD domains just don't have this pipe, avoid
3125                          * level 0 statement in that case - gd */
3126                         lvl = 3;
3127                 }
3128                 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3129                             "%s failed with error %s\n",
3130                             table->name,
3131                             nt_errstr(status) ));
3132                 TALLOC_FREE(result);
3133                 return status;
3134         }
3135
3136         DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3137                   "%s and bound anonymously.\n",
3138                   table->name,
3139                   result->desthost));
3140
3141         *presult = result;
3142         return NT_STATUS_OK;
3143 }
3144
3145 /****************************************************************************
3146  ****************************************************************************/
3147
3148 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3149                                   const struct ndr_interface_table *table,
3150                                   struct rpc_pipe_client **presult)
3151 {
3152         return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3153                                                   table, presult);
3154 }
3155
3156 /****************************************************************************
3157  Open a named pipe to an SMB server and bind using the mech specified
3158
3159  This routine references the creds pointer that is passed in
3160  ****************************************************************************/
3161
3162 NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
3163                                       const struct ndr_interface_table *table,
3164                                       enum dcerpc_transport_t transport,
3165                                       enum dcerpc_AuthType auth_type,
3166                                       enum dcerpc_AuthLevel auth_level,
3167                                       const char *server,
3168                                       struct cli_credentials *creds,
3169                                       struct rpc_pipe_client **presult)
3170 {
3171         struct rpc_pipe_client *result;
3172         struct pipe_auth_data *auth = NULL;
3173         const char *target_service = table->authservices->names[0];
3174
3175         NTSTATUS status;
3176
3177         status = cli_rpc_pipe_open(cli, transport, table, &result);
3178         if (!NT_STATUS_IS_OK(status)) {
3179                 return status;
3180         }
3181
3182         status = rpccli_generic_bind_data_from_creds(result,
3183                                                      auth_type, auth_level,
3184                                                      server, target_service,
3185                                                      creds,
3186                                                      &auth);
3187         if (!NT_STATUS_IS_OK(status)) {
3188                 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3189                           nt_errstr(status)));
3190                 goto err;
3191         }
3192
3193         status = rpc_pipe_bind(result, auth);
3194         if (!NT_STATUS_IS_OK(status)) {
3195                 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
3196                         nt_errstr(status) ));
3197                 goto err;
3198         }
3199
3200         DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
3201                 "machine %s and bound as user %s.\n", table->name,
3202                   result->desthost, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3203
3204         *presult = result;
3205         return NT_STATUS_OK;
3206
3207   err:
3208
3209         TALLOC_FREE(result);
3210         return status;
3211 }
3212
3213 /****************************************************************************
3214  Open a named pipe to an SMB server and bind using the mech specified
3215
3216  This routine steals the creds pointer that is passed in
3217  ****************************************************************************/
3218
3219 NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
3220                                         const struct ndr_interface_table *table,
3221                                         enum dcerpc_transport_t transport,
3222                                         enum credentials_use_kerberos use_kerberos,
3223                                         enum dcerpc_AuthType auth_type,
3224                                         enum dcerpc_AuthLevel auth_level,
3225                                         const char *server,
3226                                         const char *domain,
3227                                         const char *username,
3228                                         const char *password,
3229                                         struct rpc_pipe_client **presult)
3230 {
3231         struct rpc_pipe_client *result;
3232         struct pipe_auth_data *auth = NULL;
3233         const char *target_service = table->authservices->names[0];
3234         
3235         NTSTATUS status;
3236
3237         status = cli_rpc_pipe_open(cli, transport, table, &result);
3238         if (!NT_STATUS_IS_OK(status)) {
3239                 return status;
3240         }
3241
3242         status = rpccli_generic_bind_data(result,
3243                                           auth_type, auth_level,
3244                                           server, target_service,
3245                                           domain, username, password, 
3246                                           CRED_AUTO_USE_KERBEROS,
3247                                           NULL,
3248                                           &auth);
3249         if (!NT_STATUS_IS_OK(status)) {
3250                 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3251                           nt_errstr(status)));
3252                 goto err;
3253         }
3254
3255         status = rpc_pipe_bind(result, auth);
3256         if (!NT_STATUS_IS_OK(status)) {
3257                 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
3258                         nt_errstr(status) ));
3259                 goto err;
3260         }
3261
3262         DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
3263                 "machine %s and bound as user %s\\%s.\n", table->name,
3264                   result->desthost, domain, username));
3265
3266         *presult = result;
3267         return NT_STATUS_OK;
3268
3269   err:
3270
3271         TALLOC_FREE(result);
3272         return status;
3273 }
3274
3275 NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
3276                                                const struct ndr_interface_table *table,
3277                                                enum dcerpc_transport_t transport,
3278                                                struct cli_credentials *cli_creds,
3279                                                struct netlogon_creds_cli_context *netlogon_creds,
3280                                                struct rpc_pipe_client **_rpccli)
3281 {
3282         struct rpc_pipe_client *rpccli;
3283         struct pipe_auth_data *rpcauth;
3284         const char *target_service = table->authservices->names[0];
3285         struct netlogon_creds_CredentialState *ncreds = NULL;
3286         enum dcerpc_AuthLevel auth_level;
3287         NTSTATUS status;
3288         int rpc_pipe_bind_dbglvl = 0;
3289
3290         status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
3291         if (!NT_STATUS_IS_OK(status)) {
3292                 return status;
3293         }
3294
3295         status = netlogon_creds_cli_lock(netlogon_creds, rpccli, &ncreds);
3296         if (!NT_STATUS_IS_OK(status)) {
3297                 DEBUG(0, ("netlogon_creds_cli_lock returned %s\n",
3298                           nt_errstr(status)));
3299                 TALLOC_FREE(rpccli);
3300                 return status;
3301         }
3302
3303         auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
3304
3305         cli_credentials_set_netlogon_creds(cli_creds, ncreds);
3306
3307         status = rpccli_generic_bind_data_from_creds(rpccli,
3308                                                      DCERPC_AUTH_TYPE_SCHANNEL,
3309                                                      auth_level,
3310                                                      rpccli->desthost,
3311                                                      target_service,
3312                                                      cli_creds,
3313                                                      &rpcauth);
3314         if (!NT_STATUS_IS_OK(status)) {
3315                 DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
3316                           nt_errstr(status)));
3317                 TALLOC_FREE(rpccli);
3318                 return status;
3319         }
3320
3321         status = rpc_pipe_bind(rpccli, rpcauth);
3322         cli_credentials_set_netlogon_creds(cli_creds, NULL);
3323         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3324                 rpc_pipe_bind_dbglvl = 1;
3325                 netlogon_creds_cli_delete(netlogon_creds, &ncreds);
3326         }
3327         if (!NT_STATUS_IS_OK(status)) {
3328                 DEBUG(rpc_pipe_bind_dbglvl,
3329                       ("%s: rpc_pipe_bind failed with error %s\n",
3330                        __func__, nt_errstr(status)));
3331                 TALLOC_FREE(rpccli);
3332                 return status;
3333         }
3334
3335         TALLOC_FREE(ncreds);
3336
3337         if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) {
3338                 goto done;
3339         }
3340
3341         status = netlogon_creds_cli_check(netlogon_creds,
3342                                           rpccli->binding_handle);
3343         if (!NT_STATUS_IS_OK(status)) {
3344                 DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
3345                           nt_errstr(status)));
3346                 TALLOC_FREE(rpccli);
3347                 return status;
3348         }
3349
3350
3351 done:
3352         DEBUG(10,("%s: opened pipe %s to machine %s "
3353                   "for domain %s and bound using schannel.\n",
3354                   __func__, table->name,
3355                   rpccli->desthost, cli_credentials_get_domain(cli_creds)));
3356
3357         *_rpccli = rpccli;
3358         return NT_STATUS_OK;
3359 }
3360
3361 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3362                              struct rpc_pipe_client *cli,
3363                              DATA_BLOB *session_key)
3364 {
3365         NTSTATUS status;
3366         struct pipe_auth_data *a;
3367         struct gensec_security *gensec_security;
3368         DATA_BLOB sk = data_blob_null;
3369         bool make_dup = false;
3370
3371         if (!session_key || !cli) {
3372                 return NT_STATUS_INVALID_PARAMETER;
3373         }
3374
3375         a = cli->auth;
3376
3377         if (a == NULL) {
3378                 return NT_STATUS_INVALID_PARAMETER;
3379         }
3380
3381         switch (cli->auth->auth_type) {
3382         case DCERPC_AUTH_TYPE_NONE:
3383                 sk = data_blob_const(a->transport_session_key.data,
3384                                      a->transport_session_key.length);
3385                 make_dup = true;
3386                 break;
3387         default:
3388                 gensec_security = a->auth_ctx;
3389                 status = gensec_session_key(gensec_security, mem_ctx, &sk);
3390                 if (!NT_STATUS_IS_OK(status)) {
3391                         return status;
3392                 }
3393                 make_dup = false;
3394                 break;
3395         }
3396
3397         if (!sk.data) {
3398                 return NT_STATUS_NO_USER_SESSION_KEY;
3399         }
3400
3401         if (make_dup) {
3402                 *session_key = data_blob_dup_talloc(mem_ctx, sk);
3403         } else {
3404                 *session_key = sk;
3405         }
3406
3407         return NT_STATUS_OK;
3408 }