47e2854d862d17cbc5a880705b5ec31c62093935
[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                                           !state->endianess);
953         if (!NT_STATUS_IS_OK(status)) {
954                 /*
955                  * TODO: do a real async disconnect ...
956                  *
957                  * For now do it sync...
958                  */
959                 TALLOC_FREE(state->cli->transport);
960                 tevent_req_nterror(req, status);
961                 return;
962         }
963
964         status = cli_pipe_validate_current_pdu(state,
965                                                 state->cli, state->pkt,
966                                                 &state->incoming_frag,
967                                                 state->expected_pkt_type,
968                                                 state->call_id,
969                                                 &rdata,
970                                                 &state->reply_pdu);
971
972         DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
973                   (unsigned)state->incoming_frag.length,
974                   (unsigned)state->reply_pdu_offset,
975                   nt_errstr(status)));
976
977         if (state->pkt->ptype != DCERPC_PKT_FAULT && !NT_STATUS_IS_OK(status)) {
978                 /*
979                  * TODO: do a real async disconnect ...
980                  *
981                  * For now do it sync...
982                  */
983                 TALLOC_FREE(state->cli->transport);
984         } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
985                 /*
986                  * TODO: do a real async disconnect ...
987                  *
988                  * For now do it sync...
989                  */
990                 TALLOC_FREE(state->cli->transport);
991         } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
992                 /*
993                  * TODO: do a real async disconnect ...
994                  *
995                  * For now do it sync...
996                  */
997                 TALLOC_FREE(state->cli->transport);
998         }
999         if (!NT_STATUS_IS_OK(status)) {
1000                 tevent_req_nterror(req, status);
1001                 return;
1002         }
1003
1004         if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
1005             && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
1006                 /*
1007                  * Set the data type correctly for big-endian data on the
1008                  * first packet.
1009                  */
1010                 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1011                           "big-endian.\n",
1012                           rpccli_pipe_txt(talloc_tos(), state->cli)));
1013                 state->endianess = 0x00; /* BIG ENDIAN */
1014         }
1015         /*
1016          * Check endianness on subsequent packets.
1017          */
1018         if (state->endianess != state->pkt->drep[0]) {
1019                 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1020                          "%s\n",
1021                          state->endianess?"little":"big",
1022                          state->pkt->drep[0]?"little":"big"));
1023                 /*
1024                  * TODO: do a real async disconnect ...
1025                  *
1026                  * For now do it sync...
1027                  */
1028                 TALLOC_FREE(state->cli->transport);
1029                 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1030                 return;
1031         }
1032
1033         if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) {
1034                 /*
1035                  * TODO: do a real async disconnect ...
1036                  *
1037                  * For now do it sync...
1038                  */
1039                 TALLOC_FREE(state->cli->transport);
1040                 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1041                 return;
1042         }
1043
1044         /* Now copy the data portion out of the pdu into rbuf. */
1045         if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
1046                 if (!data_blob_realloc(NULL, &state->reply_pdu,
1047                                 state->reply_pdu_offset + rdata.length)) {
1048                         /*
1049                          * TODO: do a real async disconnect ...
1050                          *
1051                          * For now do it sync...
1052                          */
1053                         TALLOC_FREE(state->cli->transport);
1054                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1055                         return;
1056                 }
1057         }
1058
1059         memcpy(state->reply_pdu.data + state->reply_pdu_offset,
1060                 rdata.data, rdata.length);
1061         state->reply_pdu_offset += rdata.length;
1062
1063         /* reset state->incoming_frag, there is no need to free it,
1064          * it will be reallocated to the right size the next time
1065          * it is used */
1066         state->incoming_frag.length = 0;
1067
1068         if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1069                 /* make sure the pdu length is right now that we
1070                  * have all the data available (alloc hint may
1071                  * have allocated more than was actually used) */
1072                 state->reply_pdu.length = state->reply_pdu_offset;
1073                 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1074                           rpccli_pipe_txt(talloc_tos(), state->cli),
1075                           (unsigned)state->reply_pdu.length));
1076                 tevent_req_done(req);
1077                 return;
1078         }
1079
1080         subreq = get_complete_frag_send(state, state->ev, state->cli,
1081                                         &state->incoming_frag);
1082         if (subreq == NULL) {
1083                 /*
1084                  * TODO: do a real async disconnect ...
1085                  *
1086                  * For now do it sync...
1087                  */
1088                 TALLOC_FREE(state->cli->transport);
1089         }
1090         if (tevent_req_nomem(subreq, req)) {
1091                 return;
1092         }
1093         tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1094 }
1095
1096 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1097                                   struct ncacn_packet **pkt,
1098                                   DATA_BLOB *reply_pdu)
1099 {
1100         struct rpc_api_pipe_state *state = tevent_req_data(
1101                 req, struct rpc_api_pipe_state);
1102         NTSTATUS status;
1103
1104         if (tevent_req_is_nterror(req, &status)) {
1105                 return status;
1106         }
1107
1108         /* return data to caller and assign it ownership of memory */
1109         if (reply_pdu) {
1110                 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1111                 reply_pdu->length = state->reply_pdu.length;
1112                 state->reply_pdu.length = 0;
1113         } else {
1114                 data_blob_free(&state->reply_pdu);
1115         }
1116
1117         if (pkt) {
1118                 *pkt = talloc_steal(mem_ctx, state->pkt);
1119         }
1120
1121         return NT_STATUS_OK;
1122 }
1123
1124 /*******************************************************************
1125  Creates NTLMSSP auth bind.
1126  ********************************************************************/
1127
1128 static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1129                                                  TALLOC_CTX *mem_ctx,
1130                                                  DATA_BLOB *auth_token,
1131                                                  bool *client_hdr_signing)
1132 {
1133         struct gensec_security *gensec_security;
1134         DATA_BLOB null_blob = data_blob_null;
1135         NTSTATUS status;
1136
1137         gensec_security = cli->auth->auth_ctx;
1138
1139         DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
1140         status = gensec_update(gensec_security, mem_ctx, null_blob, auth_token);
1141
1142         if (!NT_STATUS_IS_OK(status) &&
1143             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1144         {
1145                 return status;
1146         }
1147
1148         if (client_hdr_signing == NULL) {
1149                 return status;
1150         }
1151
1152         if (cli->auth->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1153                 *client_hdr_signing = false;
1154                 return status;
1155         }
1156
1157         *client_hdr_signing = gensec_have_feature(gensec_security,
1158                                                 GENSEC_FEATURE_SIGN_PKT_HEADER);
1159
1160         return status;
1161 }
1162
1163 /*******************************************************************
1164  Creates the internals of a DCE/RPC bind request or alter context PDU.
1165  ********************************************************************/
1166
1167 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1168                                                 enum dcerpc_pkt_type ptype,
1169                                                 uint32_t rpc_call_id,
1170                                                 const struct ndr_syntax_id *abstract,
1171                                                 const struct ndr_syntax_id *transfer,
1172                                                 const DATA_BLOB *auth_info,
1173                                                 bool client_hdr_signing,
1174                                                 DATA_BLOB *blob)
1175 {
1176         uint16_t auth_len = auth_info->length;
1177         NTSTATUS status;
1178         union dcerpc_payload u;
1179         struct dcerpc_ctx_list ctx_list;
1180         uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1181
1182         if (auth_len) {
1183                 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1184         }
1185
1186         if (client_hdr_signing) {
1187                 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1188         }
1189
1190         ctx_list.context_id = 0;
1191         ctx_list.num_transfer_syntaxes = 1;
1192         ctx_list.abstract_syntax = *abstract;
1193         ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1194
1195         u.bind.max_xmit_frag    = RPC_MAX_PDU_FRAG_LEN;
1196         u.bind.max_recv_frag    = RPC_MAX_PDU_FRAG_LEN;
1197         u.bind.assoc_group_id   = 0x0;
1198         u.bind.num_contexts     = 1;
1199         u.bind.ctx_list         = &ctx_list;
1200         u.bind.auth_info        = *auth_info;
1201
1202         status = dcerpc_push_ncacn_packet(mem_ctx,
1203                                           ptype, pfc_flags,
1204                                           auth_len,
1205                                           rpc_call_id,
1206                                           &u,
1207                                           blob);
1208         if (!NT_STATUS_IS_OK(status)) {
1209                 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1210                 return status;
1211         }
1212
1213         return NT_STATUS_OK;
1214 }
1215
1216 /*******************************************************************
1217  Creates a DCE/RPC bind request.
1218  ********************************************************************/
1219
1220 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1221                                     struct rpc_pipe_client *cli,
1222                                     struct pipe_auth_data *auth,
1223                                     uint32_t rpc_call_id,
1224                                     const struct ndr_syntax_id *abstract,
1225                                     const struct ndr_syntax_id *transfer,
1226                                     DATA_BLOB *rpc_out)
1227 {
1228         DATA_BLOB auth_token = data_blob_null;
1229         DATA_BLOB auth_info = data_blob_null;
1230         NTSTATUS ret = NT_STATUS_OK;
1231
1232         switch (auth->auth_type) {
1233         case DCERPC_AUTH_TYPE_NONE:
1234                 break;
1235
1236         default:
1237                 ret = create_generic_auth_rpc_bind_req(cli, mem_ctx,
1238                                                        &auth_token,
1239                                                        &auth->client_hdr_signing);
1240
1241                 if (!NT_STATUS_IS_OK(ret) &&
1242                     !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1243                         return ret;
1244                 }
1245                 break;
1246         }
1247
1248         if (auth_token.length != 0) {
1249                 ret = dcerpc_push_dcerpc_auth(cli,
1250                                                 auth->auth_type,
1251                                                 auth->auth_level,
1252                                                 0, /* auth_pad_length */
1253                                                 auth->auth_context_id,
1254                                                 &auth_token,
1255                                                 &auth_info);
1256                 if (!NT_STATUS_IS_OK(ret)) {
1257                         return ret;
1258                 }
1259                 data_blob_free(&auth_token);
1260         }
1261
1262         ret = create_bind_or_alt_ctx_internal(mem_ctx,
1263                                               DCERPC_PKT_BIND,
1264                                               rpc_call_id,
1265                                               abstract,
1266                                               transfer,
1267                                               &auth_info,
1268                                               auth->client_hdr_signing,
1269                                               rpc_out);
1270         return ret;
1271 }
1272
1273 /*******************************************************************
1274  External interface.
1275  Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1276  Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1277  and deals with signing/sealing details.
1278  ********************************************************************/
1279
1280 struct rpc_api_pipe_req_state {
1281         struct tevent_context *ev;
1282         struct rpc_pipe_client *cli;
1283         uint8_t op_num;
1284         uint32_t call_id;
1285         const DATA_BLOB *req_data;
1286         uint32_t req_data_sent;
1287         DATA_BLOB req_trailer;
1288         uint32_t req_trailer_sent;
1289         bool verify_bitmask1;
1290         bool verify_pcontext;
1291         DATA_BLOB rpc_out;
1292         DATA_BLOB reply_pdu;
1293 };
1294
1295 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1296 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1297 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state);
1298 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1299                                   bool *is_last_frag);
1300
1301 static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1302                                          struct tevent_context *ev,
1303                                          struct rpc_pipe_client *cli,
1304                                          uint8_t op_num,
1305                                          const DATA_BLOB *req_data)
1306 {
1307         struct tevent_req *req, *subreq;
1308         struct rpc_api_pipe_req_state *state;
1309         NTSTATUS status;
1310         bool is_last_frag;
1311
1312         req = tevent_req_create(mem_ctx, &state,
1313                                 struct rpc_api_pipe_req_state);
1314         if (req == NULL) {
1315                 return NULL;
1316         }
1317         state->ev = ev;
1318         state->cli = cli;
1319         state->op_num = op_num;
1320         state->req_data = req_data;
1321         state->req_data_sent = 0;
1322         state->call_id = get_rpc_call_id();
1323         state->reply_pdu = data_blob_null;
1324         state->rpc_out = data_blob_null;
1325
1326         if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1327                                         + RPC_MAX_SIGN_SIZE) {
1328                 /* Server is screwed up ! */
1329                 status = NT_STATUS_INVALID_PARAMETER;
1330                 goto post_status;
1331         }
1332
1333         status = prepare_verification_trailer(state);
1334         if (!NT_STATUS_IS_OK(status)) {
1335                 goto post_status;
1336         }
1337
1338         status = prepare_next_frag(state, &is_last_frag);
1339         if (!NT_STATUS_IS_OK(status)) {
1340                 goto post_status;
1341         }
1342
1343         if (is_last_frag) {
1344                 subreq = rpc_api_pipe_send(state, ev, state->cli,
1345                                            &state->rpc_out,
1346                                            DCERPC_PKT_RESPONSE,
1347                                            state->call_id);
1348                 if (subreq == NULL) {
1349                         goto fail;
1350                 }
1351                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1352         } else {
1353                 subreq = rpc_write_send(state, ev, cli->transport,
1354                                         state->rpc_out.data,
1355                                         state->rpc_out.length);
1356                 if (subreq == NULL) {
1357                         goto fail;
1358                 }
1359                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1360                                         req);
1361         }
1362         return req;
1363
1364  post_status:
1365         tevent_req_nterror(req, status);
1366         return tevent_req_post(req, ev);
1367  fail:
1368         TALLOC_FREE(req);
1369         return NULL;
1370 }
1371
1372 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state)
1373 {
1374         struct pipe_auth_data *a = state->cli->auth;
1375         struct dcerpc_sec_verification_trailer *t;
1376         struct dcerpc_sec_vt *c = NULL;
1377         struct ndr_push *ndr = NULL;
1378         enum ndr_err_code ndr_err;
1379         size_t align = 0;
1380         size_t pad = 0;
1381
1382         if (a == NULL) {
1383                 return NT_STATUS_OK;
1384         }
1385
1386         if (a->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1387                 return NT_STATUS_OK;
1388         }
1389
1390         t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1391         if (t == NULL) {
1392                 return NT_STATUS_NO_MEMORY;
1393         }
1394
1395         if (!a->verified_bitmask1) {
1396                 t->commands = talloc_realloc(t, t->commands,
1397                                              struct dcerpc_sec_vt,
1398                                              t->count.count + 1);
1399                 if (t->commands == NULL) {
1400                         return NT_STATUS_NO_MEMORY;
1401                 }
1402                 c = &t->commands[t->count.count++];
1403                 ZERO_STRUCTP(c);
1404
1405                 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1406                 if (a->client_hdr_signing) {
1407                         c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1408                 }
1409                 state->verify_bitmask1 = true;
1410         }
1411
1412         if (!state->cli->verified_pcontext) {
1413                 t->commands = talloc_realloc(t, t->commands,
1414                                              struct dcerpc_sec_vt,
1415                                              t->count.count + 1);
1416                 if (t->commands == NULL) {
1417                         return NT_STATUS_NO_MEMORY;
1418                 }
1419                 c = &t->commands[t->count.count++];
1420                 ZERO_STRUCTP(c);
1421
1422                 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1423                 c->u.pcontext.abstract_syntax = state->cli->abstract_syntax;
1424                 c->u.pcontext.transfer_syntax = state->cli->transfer_syntax;
1425
1426                 state->verify_pcontext = true;
1427         }
1428
1429         if (!a->hdr_signing) {
1430                 t->commands = talloc_realloc(t, t->commands,
1431                                              struct dcerpc_sec_vt,
1432                                              t->count.count + 1);
1433                 if (t->commands == NULL) {
1434                         return NT_STATUS_NO_MEMORY;
1435                 }
1436                 c = &t->commands[t->count.count++];
1437                 ZERO_STRUCTP(c);
1438
1439                 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1440                 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1441                 c->u.header2.drep[0] = DCERPC_DREP_LE;
1442                 c->u.header2.drep[1] = 0;
1443                 c->u.header2.drep[2] = 0;
1444                 c->u.header2.drep[3] = 0;
1445                 c->u.header2.call_id = state->call_id;
1446                 c->u.header2.context_id = 0;
1447                 c->u.header2.opnum = state->op_num;
1448         }
1449
1450         if (t->count.count == 0) {
1451                 TALLOC_FREE(t);
1452                 return NT_STATUS_OK;
1453         }
1454
1455         c = &t->commands[t->count.count - 1];
1456         c->command |= DCERPC_SEC_VT_COMMAND_END;
1457
1458         if (DEBUGLEVEL >= 10) {
1459                 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1460         }
1461
1462         ndr = ndr_push_init_ctx(state);
1463         if (ndr == NULL) {
1464                 return NT_STATUS_NO_MEMORY;
1465         }
1466
1467         ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1468                                                 NDR_SCALARS | NDR_BUFFERS,
1469                                                 t);
1470         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1471                 return ndr_map_error2ntstatus(ndr_err);
1472         }
1473         state->req_trailer = ndr_push_blob(ndr);
1474
1475         align = state->req_data->length & 0x3;
1476         if (align > 0) {
1477                 pad = 4 - align;
1478         }
1479         if (pad > 0) {
1480                 bool ok;
1481                 uint8_t *p;
1482                 const uint8_t zeros[4] = { 0, };
1483
1484                 ok = data_blob_append(ndr, &state->req_trailer, zeros, pad);
1485                 if (!ok) {
1486                         return NT_STATUS_NO_MEMORY;
1487                 }
1488
1489                 /* move the padding to the start */
1490                 p = state->req_trailer.data;
1491                 memmove(p + pad, p, state->req_trailer.length - pad);
1492                 memset(p, 0, pad);
1493         }
1494
1495         return NT_STATUS_OK;
1496 }
1497
1498 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1499                                   bool *is_last_frag)
1500 {
1501         size_t auth_len;
1502         size_t frag_len;
1503         uint8_t flags = 0;
1504         size_t pad_len;
1505         size_t data_left;
1506         size_t data_thistime;
1507         size_t trailer_left;
1508         size_t trailer_thistime = 0;
1509         size_t total_left;
1510         size_t total_thistime;
1511         NTSTATUS status;
1512         bool ok;
1513         union dcerpc_payload u;
1514
1515         data_left = state->req_data->length - state->req_data_sent;
1516         trailer_left = state->req_trailer.length - state->req_trailer_sent;
1517         total_left = data_left + trailer_left;
1518         if ((total_left < data_left) || (total_left < trailer_left)) {
1519                 /*
1520                  * overflow
1521                  */
1522                 return NT_STATUS_INVALID_PARAMETER_MIX;
1523         }
1524
1525         status = dcerpc_guess_sizes(state->cli->auth,
1526                                     DCERPC_REQUEST_LENGTH, total_left,
1527                                     state->cli->max_xmit_frag,
1528                                     &total_thistime,
1529                                     &frag_len, &auth_len, &pad_len);
1530         if (!NT_STATUS_IS_OK(status)) {
1531                 return status;
1532         }
1533
1534         if (state->req_data_sent == 0) {
1535                 flags = DCERPC_PFC_FLAG_FIRST;
1536         }
1537
1538         if (total_thistime == total_left) {
1539                 flags |= DCERPC_PFC_FLAG_LAST;
1540         }
1541
1542         data_thistime = MIN(total_thistime, data_left);
1543         if (data_thistime < total_thistime) {
1544                 trailer_thistime = total_thistime - data_thistime;
1545         }
1546
1547         data_blob_free(&state->rpc_out);
1548
1549         ZERO_STRUCT(u.request);
1550
1551         u.request.alloc_hint    = total_left;
1552         u.request.context_id    = 0;
1553         u.request.opnum         = state->op_num;
1554
1555         status = dcerpc_push_ncacn_packet(state,
1556                                           DCERPC_PKT_REQUEST,
1557                                           flags,
1558                                           auth_len,
1559                                           state->call_id,
1560                                           &u,
1561                                           &state->rpc_out);
1562         if (!NT_STATUS_IS_OK(status)) {
1563                 return status;
1564         }
1565
1566         /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1567          * compute it right for requests because the auth trailer is missing
1568          * at this stage */
1569         dcerpc_set_frag_length(&state->rpc_out, frag_len);
1570
1571         if (data_thistime > 0) {
1572                 /* Copy in the data. */
1573                 ok = data_blob_append(NULL, &state->rpc_out,
1574                                 state->req_data->data + state->req_data_sent,
1575                                 data_thistime);
1576                 if (!ok) {
1577                         return NT_STATUS_NO_MEMORY;
1578                 }
1579                 state->req_data_sent += data_thistime;
1580         }
1581
1582         if (trailer_thistime > 0) {
1583                 /* Copy in the verification trailer. */
1584                 ok = data_blob_append(NULL, &state->rpc_out,
1585                                 state->req_trailer.data + state->req_trailer_sent,
1586                                 trailer_thistime);
1587                 if (!ok) {
1588                         return NT_STATUS_NO_MEMORY;
1589                 }
1590                 state->req_trailer_sent += trailer_thistime;
1591         }
1592
1593         switch (state->cli->auth->auth_level) {
1594         case DCERPC_AUTH_LEVEL_NONE:
1595         case DCERPC_AUTH_LEVEL_CONNECT:
1596         case DCERPC_AUTH_LEVEL_PACKET:
1597                 break;
1598         case DCERPC_AUTH_LEVEL_INTEGRITY:
1599         case DCERPC_AUTH_LEVEL_PRIVACY:
1600                 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1601                                                 &state->rpc_out);
1602                 if (!NT_STATUS_IS_OK(status)) {
1603                         return status;
1604                 }
1605                 break;
1606         default:
1607                 return NT_STATUS_INVALID_PARAMETER;
1608         }
1609
1610         *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1611
1612         return status;
1613 }
1614
1615 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1616 {
1617         struct tevent_req *req = tevent_req_callback_data(
1618                 subreq, struct tevent_req);
1619         struct rpc_api_pipe_req_state *state = tevent_req_data(
1620                 req, struct rpc_api_pipe_req_state);
1621         NTSTATUS status;
1622         bool is_last_frag;
1623
1624         status = rpc_write_recv(subreq);
1625         TALLOC_FREE(subreq);
1626         if (!NT_STATUS_IS_OK(status)) {
1627                 tevent_req_nterror(req, status);
1628                 return;
1629         }
1630
1631         status = prepare_next_frag(state, &is_last_frag);
1632         if (!NT_STATUS_IS_OK(status)) {
1633                 tevent_req_nterror(req, status);
1634                 return;
1635         }
1636
1637         if (is_last_frag) {
1638                 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1639                                            &state->rpc_out,
1640                                            DCERPC_PKT_RESPONSE,
1641                                            state->call_id);
1642                 if (tevent_req_nomem(subreq, req)) {
1643                         return;
1644                 }
1645                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1646         } else {
1647                 subreq = rpc_write_send(state, state->ev,
1648                                         state->cli->transport,
1649                                         state->rpc_out.data,
1650                                         state->rpc_out.length);
1651                 if (tevent_req_nomem(subreq, req)) {
1652                         return;
1653                 }
1654                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1655                                         req);
1656         }
1657 }
1658
1659 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1660 {
1661         struct tevent_req *req = tevent_req_callback_data(
1662                 subreq, struct tevent_req);
1663         struct rpc_api_pipe_req_state *state = tevent_req_data(
1664                 req, struct rpc_api_pipe_req_state);
1665         NTSTATUS status;
1666
1667         status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1668         TALLOC_FREE(subreq);
1669         if (!NT_STATUS_IS_OK(status)) {
1670                 tevent_req_nterror(req, status);
1671                 return;
1672         }
1673
1674         if (state->cli->auth == NULL) {
1675                 tevent_req_done(req);
1676                 return;
1677         }
1678
1679         if (state->verify_bitmask1) {
1680                 state->cli->auth->verified_bitmask1 = true;
1681         }
1682
1683         if (state->verify_pcontext) {
1684                 state->cli->verified_pcontext = true;
1685         }
1686
1687         tevent_req_done(req);
1688 }
1689
1690 static NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1691                                DATA_BLOB *reply_pdu)
1692 {
1693         struct rpc_api_pipe_req_state *state = tevent_req_data(
1694                 req, struct rpc_api_pipe_req_state);
1695         NTSTATUS status;
1696
1697         if (tevent_req_is_nterror(req, &status)) {
1698                 /*
1699                  * We always have to initialize to reply pdu, even if there is
1700                  * none. The rpccli_* caller routines expect this.
1701                  */
1702                 *reply_pdu = data_blob_null;
1703                 return status;
1704         }
1705
1706         /* return data to caller and assign it ownership of memory */
1707         reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1708         reply_pdu->length = state->reply_pdu.length;
1709         state->reply_pdu.length = 0;
1710
1711         return NT_STATUS_OK;
1712 }
1713
1714 /****************************************************************************
1715  Check the rpc bind acknowledge response.
1716 ****************************************************************************/
1717
1718 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1719                                 const struct ndr_syntax_id *transfer)
1720 {
1721         struct dcerpc_ack_ctx ctx;
1722
1723         if (r->secondary_address_size == 0) {
1724                 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1725         }
1726
1727         if (r->num_results < 1 || !r->ctx_list) {
1728                 return false;
1729         }
1730
1731         ctx = r->ctx_list[0];
1732
1733         /* check the transfer syntax */
1734         if ((ctx.syntax.if_version != transfer->if_version) ||
1735              (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1736                 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1737                 return False;
1738         }
1739
1740         if (r->num_results != 0x1 || ctx.result != 0) {
1741                 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1742                           r->num_results, ctx.reason.value));
1743         }
1744
1745         DEBUG(5,("check_bind_response: accepted!\n"));
1746         return True;
1747 }
1748
1749 /*******************************************************************
1750  Creates a DCE/RPC bind authentication response.
1751  This is the packet that is sent back to the server once we
1752  have received a BIND-ACK, to finish the third leg of
1753  the authentication handshake.
1754  ********************************************************************/
1755
1756 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1757                                 struct rpc_pipe_client *cli,
1758                                 struct pipe_auth_data *auth,
1759                                 uint32_t rpc_call_id,
1760                                 DATA_BLOB *pauth_blob,
1761                                 DATA_BLOB *rpc_out)
1762 {
1763         NTSTATUS status;
1764         union dcerpc_payload u;
1765
1766         u.auth3._pad = 0;
1767
1768         status = dcerpc_push_dcerpc_auth(mem_ctx,
1769                                          auth->auth_type,
1770                                          auth->auth_level,
1771                                          0, /* auth_pad_length */
1772                                          auth->auth_context_id,
1773                                          pauth_blob,
1774                                          &u.auth3.auth_info);
1775         if (!NT_STATUS_IS_OK(status)) {
1776                 return status;
1777         }
1778
1779         status = dcerpc_push_ncacn_packet(mem_ctx,
1780                                           DCERPC_PKT_AUTH3,
1781                                           DCERPC_PFC_FLAG_FIRST |
1782                                           DCERPC_PFC_FLAG_LAST,
1783                                           pauth_blob->length,
1784                                           rpc_call_id,
1785                                           &u,
1786                                           rpc_out);
1787         data_blob_free(&u.auth3.auth_info);
1788         if (!NT_STATUS_IS_OK(status)) {
1789                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1790                 return status;
1791         }
1792
1793         return NT_STATUS_OK;
1794 }
1795
1796 /*******************************************************************
1797  Creates a DCE/RPC bind alter context authentication request which
1798  may contain a spnego auth blobl
1799  ********************************************************************/
1800
1801 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1802                                         struct pipe_auth_data *auth,
1803                                         uint32_t rpc_call_id,
1804                                         const struct ndr_syntax_id *abstract,
1805                                         const struct ndr_syntax_id *transfer,
1806                                         const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1807                                         DATA_BLOB *rpc_out)
1808 {
1809         DATA_BLOB auth_info;
1810         NTSTATUS status;
1811
1812         status = dcerpc_push_dcerpc_auth(mem_ctx,
1813                                          auth->auth_type,
1814                                          auth->auth_level,
1815                                          0, /* auth_pad_length */
1816                                          auth->auth_context_id,
1817                                          pauth_blob,
1818                                          &auth_info);
1819         if (!NT_STATUS_IS_OK(status)) {
1820                 return status;
1821         }
1822
1823         status = create_bind_or_alt_ctx_internal(mem_ctx,
1824                                                  DCERPC_PKT_ALTER,
1825                                                  rpc_call_id,
1826                                                  abstract,
1827                                                  transfer,
1828                                                  &auth_info,
1829                                                  false, /* client_hdr_signing */
1830                                                  rpc_out);
1831         data_blob_free(&auth_info);
1832         return status;
1833 }
1834
1835 /****************************************************************************
1836  Do an rpc bind.
1837 ****************************************************************************/
1838
1839 struct rpc_pipe_bind_state {
1840         struct tevent_context *ev;
1841         struct rpc_pipe_client *cli;
1842         DATA_BLOB rpc_out;
1843         bool auth3;
1844         uint32_t rpc_call_id;
1845 };
1846
1847 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1848 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1849                                    struct rpc_pipe_bind_state *state,
1850                                    DATA_BLOB *credentials);
1851 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1852                                      struct rpc_pipe_bind_state *state,
1853                                      DATA_BLOB *credentials);
1854
1855 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1856                                       struct tevent_context *ev,
1857                                       struct rpc_pipe_client *cli,
1858                                       struct pipe_auth_data *auth)
1859 {
1860         struct tevent_req *req, *subreq;
1861         struct rpc_pipe_bind_state *state;
1862         NTSTATUS status;
1863
1864         req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1865         if (req == NULL) {
1866                 return NULL;
1867         }
1868
1869         DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1870                 rpccli_pipe_txt(talloc_tos(), cli),
1871                 (unsigned int)auth->auth_type,
1872                 (unsigned int)auth->auth_level ));
1873
1874         state->ev = ev;
1875         state->cli = cli;
1876         state->rpc_call_id = get_rpc_call_id();
1877
1878         cli->auth = talloc_move(cli, &auth);
1879
1880         /* Marshall the outgoing data. */
1881         status = create_rpc_bind_req(state, cli,
1882                                      cli->auth,
1883                                      state->rpc_call_id,
1884                                      &cli->abstract_syntax,
1885                                      &cli->transfer_syntax,
1886                                      &state->rpc_out);
1887
1888         if (!NT_STATUS_IS_OK(status) &&
1889             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1890                 goto post_status;
1891         }
1892
1893         subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1894                                    DCERPC_PKT_BIND_ACK, state->rpc_call_id);
1895         if (subreq == NULL) {
1896                 goto fail;
1897         }
1898         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1899         return req;
1900
1901  post_status:
1902         tevent_req_nterror(req, status);
1903         return tevent_req_post(req, ev);
1904  fail:
1905         TALLOC_FREE(req);
1906         return NULL;
1907 }
1908
1909 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1910 {
1911         struct tevent_req *req = tevent_req_callback_data(
1912                 subreq, struct tevent_req);
1913         struct rpc_pipe_bind_state *state = tevent_req_data(
1914                 req, struct rpc_pipe_bind_state);
1915         struct pipe_auth_data *pauth = state->cli->auth;
1916         struct gensec_security *gensec_security;
1917         struct ncacn_packet *pkt = NULL;
1918         struct dcerpc_auth auth;
1919         DATA_BLOB auth_token = data_blob_null;
1920         NTSTATUS status;
1921
1922         status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
1923         TALLOC_FREE(subreq);
1924         if (!NT_STATUS_IS_OK(status)) {
1925                 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1926                           rpccli_pipe_txt(talloc_tos(), state->cli),
1927                           nt_errstr(status)));
1928                 tevent_req_nterror(req, status);
1929                 return;
1930         }
1931
1932         if (state->auth3) {
1933                 tevent_req_done(req);
1934                 return;
1935         }
1936
1937         if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1938                 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1939                 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1940                 return;
1941         }
1942
1943         state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1944
1945         switch(pauth->auth_type) {
1946
1947         case DCERPC_AUTH_TYPE_NONE:
1948                 /* Bind complete. */
1949                 tevent_req_done(req);
1950                 return;
1951
1952         default:
1953                 if (pkt->auth_length == 0) {
1954                         tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1955                         return;
1956                 }
1957
1958                 /* get auth credentials */
1959                 status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
1960                                                   &pkt->u.bind_ack.auth_info,
1961                                                   &auth, NULL, true);
1962                 if (!NT_STATUS_IS_OK(status)) {
1963                         DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1964                                   nt_errstr(status)));
1965                         tevent_req_nterror(req, status);
1966                         return;
1967                 }
1968
1969                 if (auth.auth_type != pauth->auth_type) {
1970                         DEBUG(0, (__location__ " Auth type %u mismatch expected %u.\n",
1971                                   auth.auth_type, pauth->auth_type));
1972                         tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1973                         return;
1974                 }
1975
1976                 if (auth.auth_level != pauth->auth_level) {
1977                         DEBUG(0, (__location__ " Auth level %u mismatch expected %u.\n",
1978                                   auth.auth_level, pauth->auth_level));
1979                         tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1980                         return;
1981                 }
1982
1983                 if (auth.auth_context_id != pauth->auth_context_id) {
1984                         DEBUG(0, (__location__ " Auth context id %u mismatch expected %u.\n",
1985                                   (unsigned)auth.auth_context_id,
1986                                   (unsigned)pauth->auth_context_id));
1987                         tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1988                         return;
1989                 }
1990
1991                 break;
1992         }
1993
1994         /*
1995          * For authenticated binds we may need to do 3 or 4 leg binds.
1996          */
1997
1998         switch(pauth->auth_type) {
1999
2000         case DCERPC_AUTH_TYPE_NONE:
2001                 /* Bind complete. */
2002                 tevent_req_done(req);
2003                 return;
2004
2005         default:
2006                 gensec_security = pauth->auth_ctx;
2007
2008                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
2009                         if (pauth->client_hdr_signing) {
2010                                 pauth->hdr_signing = true;
2011                                 gensec_want_feature(gensec_security,
2012                                                     GENSEC_FEATURE_SIGN_PKT_HEADER);
2013                         }
2014                 }
2015
2016                 status = gensec_update(gensec_security, state,
2017                                        auth.credentials, &auth_token);
2018                 if (NT_STATUS_EQUAL(status,
2019                                     NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2020                         status = rpc_bind_next_send(req, state,
2021                                                         &auth_token);
2022                 } else if (NT_STATUS_IS_OK(status)) {
2023                         if (auth_token.length == 0) {
2024                                 /* Bind complete. */
2025                                 tevent_req_done(req);
2026                                 return;
2027                         }
2028                         status = rpc_bind_finish_send(req, state,
2029                                                         &auth_token);
2030                 }
2031                 break;
2032         }
2033
2034         if (!NT_STATUS_IS_OK(status)) {
2035                 tevent_req_nterror(req, status);
2036         }
2037         return;
2038 }
2039
2040 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
2041                                    struct rpc_pipe_bind_state *state,
2042                                    DATA_BLOB *auth_token)
2043 {
2044         struct pipe_auth_data *auth = state->cli->auth;
2045         struct tevent_req *subreq;
2046         NTSTATUS status;
2047
2048         /* Now prepare the alter context pdu. */
2049         data_blob_free(&state->rpc_out);
2050
2051         status = create_rpc_alter_context(state, auth,
2052                                           state->rpc_call_id,
2053                                           &state->cli->abstract_syntax,
2054                                           &state->cli->transfer_syntax,
2055                                           auth_token,
2056                                           &state->rpc_out);
2057         if (!NT_STATUS_IS_OK(status)) {
2058                 return status;
2059         }
2060
2061         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2062                                    &state->rpc_out, DCERPC_PKT_ALTER_RESP,
2063                                    state->rpc_call_id);
2064         if (subreq == NULL) {
2065                 return NT_STATUS_NO_MEMORY;
2066         }
2067         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2068         return NT_STATUS_OK;
2069 }
2070
2071 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
2072                                      struct rpc_pipe_bind_state *state,
2073                                      DATA_BLOB *auth_token)
2074 {
2075         struct pipe_auth_data *auth = state->cli->auth;
2076         struct tevent_req *subreq;
2077         NTSTATUS status;
2078
2079         state->auth3 = true;
2080
2081         /* Now prepare the auth3 context pdu. */
2082         data_blob_free(&state->rpc_out);
2083
2084         status = create_rpc_bind_auth3(state, state->cli, auth,
2085                                         state->rpc_call_id,
2086                                         auth_token,
2087                                         &state->rpc_out);
2088         if (!NT_STATUS_IS_OK(status)) {
2089                 return status;
2090         }
2091
2092         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2093                                    &state->rpc_out, DCERPC_PKT_AUTH3,
2094                                    state->rpc_call_id);
2095         if (subreq == NULL) {
2096                 return NT_STATUS_NO_MEMORY;
2097         }
2098         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2099         return NT_STATUS_OK;
2100 }
2101
2102 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2103 {
2104         return tevent_req_simple_recv_ntstatus(req);
2105 }
2106
2107 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2108                        struct pipe_auth_data *auth)
2109 {
2110         TALLOC_CTX *frame = talloc_stackframe();
2111         struct tevent_context *ev;
2112         struct tevent_req *req;
2113         NTSTATUS status = NT_STATUS_OK;
2114
2115         ev = samba_tevent_context_init(frame);
2116         if (ev == NULL) {
2117                 status = NT_STATUS_NO_MEMORY;
2118                 goto fail;
2119         }
2120
2121         req = rpc_pipe_bind_send(frame, ev, cli, auth);
2122         if (req == NULL) {
2123                 status = NT_STATUS_NO_MEMORY;
2124                 goto fail;
2125         }
2126
2127         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2128                 goto fail;
2129         }
2130
2131         status = rpc_pipe_bind_recv(req);
2132  fail:
2133         TALLOC_FREE(frame);
2134         return status;
2135 }
2136
2137 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2138
2139 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2140                                 unsigned int timeout)
2141 {
2142         unsigned int old;
2143
2144         if (rpc_cli->transport == NULL) {
2145                 return RPCCLI_DEFAULT_TIMEOUT;
2146         }
2147
2148         if (rpc_cli->transport->set_timeout == NULL) {
2149                 return RPCCLI_DEFAULT_TIMEOUT;
2150         }
2151
2152         old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2153         if (old == 0) {
2154                 return RPCCLI_DEFAULT_TIMEOUT;
2155         }
2156
2157         return old;
2158 }
2159
2160 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2161 {
2162         if (rpc_cli == NULL) {
2163                 return false;
2164         }
2165
2166         if (rpc_cli->transport == NULL) {
2167                 return false;
2168         }
2169
2170         return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2171 }
2172
2173 struct rpccli_bh_state {
2174         struct rpc_pipe_client *rpc_cli;
2175 };
2176
2177 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2178 {
2179         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2180                                      struct rpccli_bh_state);
2181
2182         return rpccli_is_connected(hs->rpc_cli);
2183 }
2184
2185 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2186                                       uint32_t timeout)
2187 {
2188         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2189                                      struct rpccli_bh_state);
2190
2191         return rpccli_set_timeout(hs->rpc_cli, timeout);
2192 }
2193
2194 static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
2195                                 enum dcerpc_AuthType *auth_type,
2196                                 enum dcerpc_AuthLevel *auth_level)
2197 {
2198         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2199                                      struct rpccli_bh_state);
2200
2201         if (hs->rpc_cli == NULL) {
2202                 return;
2203         }
2204
2205         if (hs->rpc_cli->auth == NULL) {
2206                 return;
2207         }
2208
2209         *auth_type = hs->rpc_cli->auth->auth_type;
2210         *auth_level = hs->rpc_cli->auth->auth_level;
2211 }
2212
2213 struct rpccli_bh_raw_call_state {
2214         DATA_BLOB in_data;
2215         DATA_BLOB out_data;
2216         uint32_t out_flags;
2217 };
2218
2219 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2220
2221 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2222                                                   struct tevent_context *ev,
2223                                                   struct dcerpc_binding_handle *h,
2224                                                   const struct GUID *object,
2225                                                   uint32_t opnum,
2226                                                   uint32_t in_flags,
2227                                                   const uint8_t *in_data,
2228                                                   size_t in_length)
2229 {
2230         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2231                                      struct rpccli_bh_state);
2232         struct tevent_req *req;
2233         struct rpccli_bh_raw_call_state *state;
2234         bool ok;
2235         struct tevent_req *subreq;
2236
2237         req = tevent_req_create(mem_ctx, &state,
2238                                 struct rpccli_bh_raw_call_state);
2239         if (req == NULL) {
2240                 return NULL;
2241         }
2242         state->in_data.data = discard_const_p(uint8_t, in_data);
2243         state->in_data.length = in_length;
2244
2245         ok = rpccli_bh_is_connected(h);
2246         if (!ok) {
2247                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2248                 return tevent_req_post(req, ev);
2249         }
2250
2251         subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2252                                        opnum, &state->in_data);
2253         if (tevent_req_nomem(subreq, req)) {
2254                 return tevent_req_post(req, ev);
2255         }
2256         tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2257
2258         return req;
2259 }
2260
2261 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2262 {
2263         struct tevent_req *req =
2264                 tevent_req_callback_data(subreq,
2265                 struct tevent_req);
2266         struct rpccli_bh_raw_call_state *state =
2267                 tevent_req_data(req,
2268                 struct rpccli_bh_raw_call_state);
2269         NTSTATUS status;
2270
2271         state->out_flags = 0;
2272
2273         /* TODO: support bigendian responses */
2274
2275         status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2276         TALLOC_FREE(subreq);
2277         if (!NT_STATUS_IS_OK(status)) {
2278                 tevent_req_nterror(req, status);
2279                 return;
2280         }
2281
2282         tevent_req_done(req);
2283 }
2284
2285 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2286                                         TALLOC_CTX *mem_ctx,
2287                                         uint8_t **out_data,
2288                                         size_t *out_length,
2289                                         uint32_t *out_flags)
2290 {
2291         struct rpccli_bh_raw_call_state *state =
2292                 tevent_req_data(req,
2293                 struct rpccli_bh_raw_call_state);
2294         NTSTATUS status;
2295
2296         if (tevent_req_is_nterror(req, &status)) {
2297                 tevent_req_received(req);
2298                 return status;
2299         }
2300
2301         *out_data = talloc_move(mem_ctx, &state->out_data.data);
2302         *out_length = state->out_data.length;
2303         *out_flags = state->out_flags;
2304         tevent_req_received(req);
2305         return NT_STATUS_OK;
2306 }
2307
2308 struct rpccli_bh_disconnect_state {
2309         uint8_t _dummy;
2310 };
2311
2312 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2313                                                 struct tevent_context *ev,
2314                                                 struct dcerpc_binding_handle *h)
2315 {
2316         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2317                                      struct rpccli_bh_state);
2318         struct tevent_req *req;
2319         struct rpccli_bh_disconnect_state *state;
2320         bool ok;
2321
2322         req = tevent_req_create(mem_ctx, &state,
2323                                 struct rpccli_bh_disconnect_state);
2324         if (req == NULL) {
2325                 return NULL;
2326         }
2327
2328         ok = rpccli_bh_is_connected(h);
2329         if (!ok) {
2330                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2331                 return tevent_req_post(req, ev);
2332         }
2333
2334         /*
2335          * TODO: do a real async disconnect ...
2336          *
2337          * For now we do it sync...
2338          */
2339         TALLOC_FREE(hs->rpc_cli->transport);
2340         hs->rpc_cli = NULL;
2341
2342         tevent_req_done(req);
2343         return tevent_req_post(req, ev);
2344 }
2345
2346 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2347 {
2348         NTSTATUS status;
2349
2350         if (tevent_req_is_nterror(req, &status)) {
2351                 tevent_req_received(req);
2352                 return status;
2353         }
2354
2355         tevent_req_received(req);
2356         return NT_STATUS_OK;
2357 }
2358
2359 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2360 {
2361         return true;
2362 }
2363
2364 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2365                                    int ndr_flags,
2366                                    const void *_struct_ptr,
2367                                    const struct ndr_interface_call *call)
2368 {
2369         void *struct_ptr = discard_const(_struct_ptr);
2370
2371         if (DEBUGLEVEL < 10) {
2372                 return;
2373         }
2374
2375         if (ndr_flags & NDR_IN) {
2376                 ndr_print_function_debug(call->ndr_print,
2377                                          call->name,
2378                                          ndr_flags,
2379                                          struct_ptr);
2380         }
2381         if (ndr_flags & NDR_OUT) {
2382                 ndr_print_function_debug(call->ndr_print,
2383                                          call->name,
2384                                          ndr_flags,
2385                                          struct_ptr);
2386         }
2387 }
2388
2389 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2390         .name                   = "rpccli",
2391         .is_connected           = rpccli_bh_is_connected,
2392         .set_timeout            = rpccli_bh_set_timeout,
2393         .auth_info              = rpccli_bh_auth_info,
2394         .raw_call_send          = rpccli_bh_raw_call_send,
2395         .raw_call_recv          = rpccli_bh_raw_call_recv,
2396         .disconnect_send        = rpccli_bh_disconnect_send,
2397         .disconnect_recv        = rpccli_bh_disconnect_recv,
2398
2399         .ref_alloc              = rpccli_bh_ref_alloc,
2400         .do_ndr_print           = rpccli_bh_do_ndr_print,
2401 };
2402
2403 /* initialise a rpc_pipe_client binding handle */
2404 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2405                                         const struct GUID *object,
2406                                         const struct ndr_interface_table *table)
2407 {
2408         struct dcerpc_binding_handle *h;
2409         struct rpccli_bh_state *hs;
2410
2411         h = dcerpc_binding_handle_create(c,
2412                                          &rpccli_bh_ops,
2413                                          object,
2414                                          table,
2415                                          &hs,
2416                                          struct rpccli_bh_state,
2417                                          __location__);
2418         if (h == NULL) {
2419                 return NULL;
2420         }
2421         hs->rpc_cli = c;
2422
2423         return h;
2424 }
2425
2426 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2427                                struct pipe_auth_data **presult)
2428 {
2429         struct pipe_auth_data *result;
2430         struct auth_generic_state *auth_generic_ctx;
2431         NTSTATUS status;
2432
2433         result = talloc_zero(mem_ctx, struct pipe_auth_data);
2434         if (result == NULL) {
2435                 return NT_STATUS_NO_MEMORY;
2436         }
2437
2438         result->auth_type = DCERPC_AUTH_TYPE_NONE;
2439         result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2440         result->auth_context_id = 0;
2441
2442         status = auth_generic_client_prepare(result,
2443                                              &auth_generic_ctx);
2444         if (!NT_STATUS_IS_OK(status)) {
2445                 DEBUG(1, ("Failed to create auth_generic context: %s\n",
2446                           nt_errstr(status)));
2447         }
2448
2449         status = auth_generic_set_username(auth_generic_ctx, "");
2450         if (!NT_STATUS_IS_OK(status)) {
2451                 DEBUG(1, ("Failed to set username: %s\n",
2452                           nt_errstr(status)));
2453         }
2454
2455         status = auth_generic_set_domain(auth_generic_ctx, "");
2456         if (!NT_STATUS_IS_OK(status)) {
2457                 DEBUG(1, ("Failed to set domain: %s\n",
2458                           nt_errstr(status)));
2459                 return status;
2460         }
2461
2462         status = gensec_set_credentials(auth_generic_ctx->gensec_security,
2463                                         auth_generic_ctx->credentials);
2464         if (!NT_STATUS_IS_OK(status)) {
2465                 DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
2466                           nt_errstr(status)));
2467                 return status;
2468         }
2469         talloc_unlink(auth_generic_ctx, auth_generic_ctx->credentials);
2470         auth_generic_ctx->credentials = NULL;
2471
2472         result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2473         talloc_free(auth_generic_ctx);
2474         *presult = result;
2475         return NT_STATUS_OK;
2476 }
2477
2478 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2479                                          enum dcerpc_AuthType auth_type,
2480                                          enum dcerpc_AuthLevel auth_level,
2481                                          const char *server,
2482                                          const char *target_service,
2483                                          const char *domain,
2484                                          const char *username,
2485                                          const char *password,
2486                                          enum credentials_use_kerberos use_kerberos,
2487                                          struct netlogon_creds_CredentialState *creds,
2488                                          struct pipe_auth_data **presult)
2489 {
2490         struct auth_generic_state *auth_generic_ctx;
2491         struct pipe_auth_data *result;
2492         NTSTATUS status;
2493
2494         result = talloc_zero(mem_ctx, struct pipe_auth_data);
2495         if (result == NULL) {
2496                 return NT_STATUS_NO_MEMORY;
2497         }
2498
2499         result->auth_type = auth_type;
2500         result->auth_level = auth_level;
2501         result->auth_context_id = 1;
2502
2503         status = auth_generic_client_prepare(result,
2504                                              &auth_generic_ctx);
2505         if (!NT_STATUS_IS_OK(status)) {
2506                 goto fail;
2507         }
2508
2509         status = auth_generic_set_username(auth_generic_ctx, username);
2510         if (!NT_STATUS_IS_OK(status)) {
2511                 goto fail;
2512         }
2513
2514         status = auth_generic_set_domain(auth_generic_ctx, domain);
2515         if (!NT_STATUS_IS_OK(status)) {
2516                 goto fail;
2517         }
2518
2519         status = auth_generic_set_password(auth_generic_ctx, password);
2520         if (!NT_STATUS_IS_OK(status)) {
2521                 goto fail;
2522         }
2523
2524         status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2525         if (!NT_STATUS_IS_OK(status)) {
2526                 goto fail;
2527         }
2528
2529         status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2530         if (!NT_STATUS_IS_OK(status)) {
2531                 goto fail;
2532         }
2533
2534         cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos);
2535         cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
2536
2537         status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2538         if (!NT_STATUS_IS_OK(status)) {
2539                 goto fail;
2540         }
2541
2542         result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2543         talloc_free(auth_generic_ctx);
2544         *presult = result;
2545         return NT_STATUS_OK;
2546
2547  fail:
2548         TALLOC_FREE(result);
2549         return status;
2550 }
2551
2552 /* This routine steals the creds pointer that is passed in */
2553 static NTSTATUS rpccli_generic_bind_data_from_creds(TALLOC_CTX *mem_ctx,
2554                                                     enum dcerpc_AuthType auth_type,
2555                                                     enum dcerpc_AuthLevel auth_level,
2556                                                     const char *server,
2557                                                     const char *target_service,
2558                                                     struct cli_credentials *creds,
2559                                                     struct pipe_auth_data **presult)
2560 {
2561         struct auth_generic_state *auth_generic_ctx;
2562         struct pipe_auth_data *result;
2563         NTSTATUS status;
2564
2565         result = talloc_zero(mem_ctx, struct pipe_auth_data);
2566         if (result == NULL) {
2567                 return NT_STATUS_NO_MEMORY;
2568         }
2569
2570         result->auth_type = auth_type;
2571         result->auth_level = auth_level;
2572         result->auth_context_id = 1;
2573
2574         status = auth_generic_client_prepare(result,
2575                                              &auth_generic_ctx);
2576         if (!NT_STATUS_IS_OK(status)) {
2577                 goto fail;
2578         }
2579
2580         status = auth_generic_set_creds(auth_generic_ctx, creds);
2581         if (!NT_STATUS_IS_OK(status)) {
2582                 goto fail;
2583         }
2584
2585         status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2586         if (!NT_STATUS_IS_OK(status)) {
2587                 goto fail;
2588         }
2589
2590         status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2591         if (!NT_STATUS_IS_OK(status)) {
2592                 goto fail;
2593         }
2594
2595         status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2596         if (!NT_STATUS_IS_OK(status)) {
2597                 goto fail;
2598         }
2599
2600         result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2601         talloc_free(auth_generic_ctx);
2602         *presult = result;
2603         return NT_STATUS_OK;
2604
2605  fail:
2606         TALLOC_FREE(result);
2607         return status;
2608 }
2609
2610 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2611                                   struct pipe_auth_data **presult)
2612 {
2613         return rpccli_generic_bind_data(mem_ctx,
2614                                         DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
2615                                         DCERPC_AUTH_LEVEL_CONNECT,
2616                                         NULL, /* server */
2617                                         "host", /* target_service */
2618                                         NAME_NT_AUTHORITY, /* domain */
2619                                         "SYSTEM",
2620                                         "", /* password */
2621                                         CRED_DONT_USE_KERBEROS,
2622                                         NULL, /* netlogon_creds_CredentialState */
2623                                         presult);
2624 }
2625
2626 /**
2627  * Create an rpc pipe client struct, connecting to a tcp port.
2628  */
2629 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2630                                        const struct sockaddr_storage *ss_addr,
2631                                        uint16_t port,
2632                                        const struct ndr_interface_table *table,
2633                                        struct rpc_pipe_client **presult)
2634 {
2635         struct rpc_pipe_client *result;
2636         struct sockaddr_storage addr;
2637         NTSTATUS status;
2638         int fd;
2639
2640         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2641         if (result == NULL) {
2642                 return NT_STATUS_NO_MEMORY;
2643         }
2644
2645         result->abstract_syntax = table->syntax_id;
2646         result->transfer_syntax = ndr_transfer_syntax_ndr;
2647
2648         result->desthost = talloc_strdup(result, host);
2649         result->srv_name_slash = talloc_asprintf_strupper_m(
2650                 result, "\\\\%s", result->desthost);
2651         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2652                 status = NT_STATUS_NO_MEMORY;
2653                 goto fail;
2654         }
2655
2656         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2657
2658         if (ss_addr == NULL) {
2659                 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2660                         status = NT_STATUS_NOT_FOUND;
2661                         goto fail;
2662                 }
2663         } else {
2664                 addr = *ss_addr;
2665         }
2666
2667         status = open_socket_out(&addr, port, 60*1000, &fd);
2668         if (!NT_STATUS_IS_OK(status)) {
2669                 goto fail;
2670         }
2671         set_socket_options(fd, lp_socket_options());
2672
2673         status = rpc_transport_sock_init(result, fd, &result->transport);
2674         if (!NT_STATUS_IS_OK(status)) {
2675                 close(fd);
2676                 goto fail;
2677         }
2678
2679         result->transport->transport = NCACN_IP_TCP;
2680
2681         result->binding_handle = rpccli_bh_create(result, NULL, table);
2682         if (result->binding_handle == NULL) {
2683                 TALLOC_FREE(result);
2684                 return NT_STATUS_NO_MEMORY;
2685         }
2686
2687         *presult = result;
2688         return NT_STATUS_OK;
2689
2690  fail:
2691         TALLOC_FREE(result);
2692         return status;
2693 }
2694
2695 /**
2696  * Determine the tcp port on which a dcerpc interface is listening
2697  * for the ncacn_ip_tcp transport via the endpoint mapper of the
2698  * target host.
2699  */
2700 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2701                                       const struct sockaddr_storage *addr,
2702                                       const struct ndr_interface_table *table,
2703                                       uint16_t *pport)
2704 {
2705         NTSTATUS status;
2706         struct rpc_pipe_client *epm_pipe = NULL;
2707         struct dcerpc_binding_handle *epm_handle = NULL;
2708         struct pipe_auth_data *auth = NULL;
2709         struct dcerpc_binding *map_binding = NULL;
2710         struct dcerpc_binding *res_binding = NULL;
2711         enum dcerpc_transport_t transport;
2712         const char *endpoint = NULL;
2713         struct epm_twr_t *map_tower = NULL;
2714         struct epm_twr_t *res_towers = NULL;
2715         struct policy_handle *entry_handle = NULL;
2716         uint32_t num_towers = 0;
2717         uint32_t max_towers = 1;
2718         struct epm_twr_p_t towers;
2719         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2720         uint32_t result = 0;
2721
2722         if (pport == NULL) {
2723                 status = NT_STATUS_INVALID_PARAMETER;
2724                 goto done;
2725         }
2726
2727         if (ndr_syntax_id_equal(&table->syntax_id,
2728                                 &ndr_table_epmapper.syntax_id)) {
2729                 *pport = 135;
2730                 status = NT_STATUS_OK;
2731                 goto done;
2732         }
2733
2734         /* open the connection to the endpoint mapper */
2735         status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2736                                         &ndr_table_epmapper,
2737                                         &epm_pipe);
2738
2739         if (!NT_STATUS_IS_OK(status)) {
2740                 goto done;
2741         }
2742         epm_handle = epm_pipe->binding_handle;
2743
2744         status = rpccli_anon_bind_data(tmp_ctx, &auth);
2745         if (!NT_STATUS_IS_OK(status)) {
2746                 goto done;
2747         }
2748
2749         status = rpc_pipe_bind(epm_pipe, auth);
2750         if (!NT_STATUS_IS_OK(status)) {
2751                 goto done;
2752         }
2753
2754         /* create tower for asking the epmapper */
2755
2756         status = dcerpc_parse_binding(tmp_ctx, "ncacn_ip_tcp:[135]",
2757                                       &map_binding);
2758         if (!NT_STATUS_IS_OK(status)) {
2759                 goto done;
2760         }
2761
2762         status = dcerpc_binding_set_abstract_syntax(map_binding,
2763                                                     &table->syntax_id);
2764         if (!NT_STATUS_IS_OK(status)) {
2765                 goto done;
2766         }
2767
2768         map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
2769         if (map_tower == NULL) {
2770                 status = NT_STATUS_NO_MEMORY;
2771                 goto done;
2772         }
2773
2774         status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2775                                             &(map_tower->tower));
2776         if (!NT_STATUS_IS_OK(status)) {
2777                 goto done;
2778         }
2779
2780         /* allocate further parameters for the epm_Map call */
2781
2782         res_towers = talloc_array(tmp_ctx, struct epm_twr_t, max_towers);
2783         if (res_towers == NULL) {
2784                 status = NT_STATUS_NO_MEMORY;
2785                 goto done;
2786         }
2787         towers.twr = res_towers;
2788
2789         entry_handle = talloc_zero(tmp_ctx, struct policy_handle);
2790         if (entry_handle == NULL) {
2791                 status = NT_STATUS_NO_MEMORY;
2792                 goto done;
2793         }
2794
2795         /* ask the endpoint mapper for the port */
2796
2797         status = dcerpc_epm_Map(epm_handle,
2798                                 tmp_ctx,
2799                                 discard_const_p(struct GUID,
2800                                               &(table->syntax_id.uuid)),
2801                                 map_tower,
2802                                 entry_handle,
2803                                 max_towers,
2804                                 &num_towers,
2805                                 &towers,
2806                                 &result);
2807
2808         if (!NT_STATUS_IS_OK(status)) {
2809                 goto done;
2810         }
2811
2812         if (result != EPMAPPER_STATUS_OK) {
2813                 status = NT_STATUS_UNSUCCESSFUL;
2814                 goto done;
2815         }
2816
2817         if (num_towers != 1) {
2818                 status = NT_STATUS_UNSUCCESSFUL;
2819                 goto done;
2820         }
2821
2822         /* extract the port from the answer */
2823
2824         status = dcerpc_binding_from_tower(tmp_ctx,
2825                                            &(towers.twr->tower),
2826                                            &res_binding);
2827         if (!NT_STATUS_IS_OK(status)) {
2828                 goto done;
2829         }
2830
2831         transport = dcerpc_binding_get_transport(res_binding);
2832         endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
2833
2834         /* are further checks here necessary? */
2835         if (transport != NCACN_IP_TCP) {
2836                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2837                 goto done;
2838         }
2839
2840         if (endpoint == NULL) {
2841                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2842                 goto done;
2843         }
2844
2845         *pport = (uint16_t)atoi(endpoint);
2846
2847 done:
2848         TALLOC_FREE(tmp_ctx);
2849         return status;
2850 }
2851
2852 /**
2853  * Create a rpc pipe client struct, connecting to a host via tcp.
2854  * The port is determined by asking the endpoint mapper on the given
2855  * host.
2856  */
2857 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2858                            const struct sockaddr_storage *addr,
2859                            const struct ndr_interface_table *table,
2860                            struct rpc_pipe_client **presult)
2861 {
2862         NTSTATUS status;
2863         uint16_t port = 0;
2864
2865         status = rpc_pipe_get_tcp_port(host, addr, table, &port);
2866         if (!NT_STATUS_IS_OK(status)) {
2867                 return status;
2868         }
2869
2870         return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2871                                       table, presult);
2872 }
2873
2874 /********************************************************************
2875  Create a rpc pipe client struct, connecting to a unix domain socket
2876  ********************************************************************/
2877 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2878                                const struct ndr_interface_table *table,
2879                                struct rpc_pipe_client **presult)
2880 {
2881         struct rpc_pipe_client *result;
2882         struct sockaddr_un addr;
2883         NTSTATUS status;
2884         int fd;
2885         socklen_t salen;
2886
2887         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2888         if (result == NULL) {
2889                 return NT_STATUS_NO_MEMORY;
2890         }
2891
2892         result->abstract_syntax = table->syntax_id;
2893         result->transfer_syntax = ndr_transfer_syntax_ndr;
2894
2895         result->desthost = get_myname(result);
2896         result->srv_name_slash = talloc_asprintf_strupper_m(
2897                 result, "\\\\%s", result->desthost);
2898         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2899                 status = NT_STATUS_NO_MEMORY;
2900                 goto fail;
2901         }
2902
2903         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2904
2905         fd = socket(AF_UNIX, SOCK_STREAM, 0);
2906         if (fd == -1) {
2907                 status = map_nt_error_from_unix(errno);
2908                 goto fail;
2909         }
2910
2911         ZERO_STRUCT(addr);
2912         addr.sun_family = AF_UNIX;
2913         strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2914         salen = sizeof(struct sockaddr_un);
2915
2916         if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
2917                 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2918                           strerror(errno)));
2919                 close(fd);
2920                 return map_nt_error_from_unix(errno);
2921         }
2922
2923         status = rpc_transport_sock_init(result, fd, &result->transport);
2924         if (!NT_STATUS_IS_OK(status)) {
2925                 close(fd);
2926                 goto fail;
2927         }
2928
2929         result->transport->transport = NCALRPC;
2930
2931         result->binding_handle = rpccli_bh_create(result, NULL, table);
2932         if (result->binding_handle == NULL) {
2933                 TALLOC_FREE(result);
2934                 return NT_STATUS_NO_MEMORY;
2935         }
2936
2937         *presult = result;
2938         return NT_STATUS_OK;
2939
2940  fail:
2941         TALLOC_FREE(result);
2942         return status;
2943 }
2944
2945 struct rpc_pipe_client_np_ref {
2946         struct cli_state *cli;
2947         struct rpc_pipe_client *pipe;
2948 };
2949
2950 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2951 {
2952         DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2953         return 0;
2954 }
2955
2956 /****************************************************************************
2957  Open a named pipe over SMB to a remote server.
2958  *
2959  * CAVEAT CALLER OF THIS FUNCTION:
2960  *    The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2961  *    so be sure that this function is called AFTER any structure (vs pointer)
2962  *    assignment of the cli.  In particular, libsmbclient does structure
2963  *    assignments of cli, which invalidates the data in the returned
2964  *    rpc_pipe_client if this function is called before the structure assignment
2965  *    of cli.
2966  * 
2967  ****************************************************************************/
2968
2969 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2970                                  const struct ndr_interface_table *table,
2971                                  struct rpc_pipe_client **presult)
2972 {
2973         struct rpc_pipe_client *result;
2974         NTSTATUS status;
2975         struct rpc_pipe_client_np_ref *np_ref;
2976
2977         /* sanity check to protect against crashes */
2978
2979         if ( !cli ) {
2980                 return NT_STATUS_INVALID_HANDLE;
2981         }
2982
2983         result = talloc_zero(NULL, struct rpc_pipe_client);
2984         if (result == NULL) {
2985                 return NT_STATUS_NO_MEMORY;
2986         }
2987
2988         result->abstract_syntax = table->syntax_id;
2989         result->transfer_syntax = ndr_transfer_syntax_ndr;
2990         result->desthost = talloc_strdup(result, smbXcli_conn_remote_name(cli->conn));
2991         result->srv_name_slash = talloc_asprintf_strupper_m(
2992                 result, "\\\\%s", result->desthost);
2993
2994         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2995
2996         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2997                 TALLOC_FREE(result);
2998                 return NT_STATUS_NO_MEMORY;
2999         }
3000
3001         status = rpc_transport_np_init(result, cli, table,
3002                                        &result->transport);
3003         if (!NT_STATUS_IS_OK(status)) {
3004                 TALLOC_FREE(result);
3005                 return status;
3006         }
3007
3008         result->transport->transport = NCACN_NP;
3009
3010         np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3011         if (np_ref == NULL) {
3012                 TALLOC_FREE(result);
3013                 return NT_STATUS_NO_MEMORY;
3014         }
3015         np_ref->cli = cli;
3016         np_ref->pipe = result;
3017
3018         DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3019         talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3020
3021         result->binding_handle = rpccli_bh_create(result, NULL, table);
3022         if (result->binding_handle == NULL) {
3023                 TALLOC_FREE(result);
3024                 return NT_STATUS_NO_MEMORY;
3025         }
3026
3027         *presult = result;
3028         return NT_STATUS_OK;
3029 }
3030
3031 /****************************************************************************
3032  Open a pipe to a remote server.
3033  ****************************************************************************/
3034
3035 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3036                                   enum dcerpc_transport_t transport,
3037                                   const struct ndr_interface_table *table,
3038                                   struct rpc_pipe_client **presult)
3039 {
3040         switch (transport) {
3041         case NCACN_IP_TCP:
3042                 return rpc_pipe_open_tcp(NULL,
3043                                          smbXcli_conn_remote_name(cli->conn),
3044                                          smbXcli_conn_remote_sockaddr(cli->conn),
3045                                          table, presult);
3046         case NCACN_NP:
3047                 return rpc_pipe_open_np(cli, table, presult);
3048         default:
3049                 return NT_STATUS_NOT_IMPLEMENTED;
3050         }
3051 }
3052
3053 /****************************************************************************
3054  Open a named pipe to an SMB server and bind anonymously.
3055  ****************************************************************************/
3056
3057 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3058                                             enum dcerpc_transport_t transport,
3059                                             const struct ndr_interface_table *table,
3060                                             struct rpc_pipe_client **presult)
3061 {
3062         struct rpc_pipe_client *result;
3063         struct pipe_auth_data *auth;
3064         NTSTATUS status;
3065
3066         status = cli_rpc_pipe_open(cli, transport, table, &result);
3067         if (!NT_STATUS_IS_OK(status)) {
3068                 return status;
3069         }
3070
3071         status = rpccli_anon_bind_data(result, &auth);
3072         if (!NT_STATUS_IS_OK(status)) {
3073                 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3074                           nt_errstr(status)));
3075                 TALLOC_FREE(result);
3076                 return status;
3077         }
3078
3079         /*
3080          * This is a bit of an abstraction violation due to the fact that an
3081          * anonymous bind on an authenticated SMB inherits the user/domain
3082          * from the enclosing SMB creds
3083          */
3084
3085         if (transport == NCACN_NP) {
3086                 struct smbXcli_session *session;
3087
3088                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3089                         session = cli->smb2.session;
3090                 } else {
3091                         session = cli->smb1.session;
3092                 }
3093
3094                 status = smbXcli_session_application_key(session, auth,
3095                                                 &auth->transport_session_key);
3096                 if (!NT_STATUS_IS_OK(status)) {
3097                         auth->transport_session_key = data_blob_null;
3098                 }
3099         }
3100
3101         status = rpc_pipe_bind(result, auth);
3102         if (!NT_STATUS_IS_OK(status)) {
3103                 int lvl = 0;
3104                 if (ndr_syntax_id_equal(&table->syntax_id,
3105                                         &ndr_table_dssetup.syntax_id)) {
3106                         /* non AD domains just don't have this pipe, avoid
3107                          * level 0 statement in that case - gd */
3108                         lvl = 3;
3109                 }
3110                 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3111                             "%s failed with error %s\n",
3112                             table->name,
3113                             nt_errstr(status) ));
3114                 TALLOC_FREE(result);
3115                 return status;
3116         }
3117
3118         DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3119                   "%s and bound anonymously.\n",
3120                   table->name,
3121                   result->desthost));
3122
3123         *presult = result;
3124         return NT_STATUS_OK;
3125 }
3126
3127 /****************************************************************************
3128  ****************************************************************************/
3129
3130 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3131                                   const struct ndr_interface_table *table,
3132                                   struct rpc_pipe_client **presult)
3133 {
3134         return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3135                                                   table, presult);
3136 }
3137
3138 /****************************************************************************
3139  Open a named pipe to an SMB server and bind using the mech specified
3140
3141  This routine references the creds pointer that is passed in
3142  ****************************************************************************/
3143
3144 NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
3145                                       const struct ndr_interface_table *table,
3146                                       enum dcerpc_transport_t transport,
3147                                       enum dcerpc_AuthType auth_type,
3148                                       enum dcerpc_AuthLevel auth_level,
3149                                       const char *server,
3150                                       struct cli_credentials *creds,
3151                                       struct rpc_pipe_client **presult)
3152 {
3153         struct rpc_pipe_client *result;
3154         struct pipe_auth_data *auth = NULL;
3155         const char *target_service = table->authservices->names[0];
3156
3157         NTSTATUS status;
3158
3159         status = cli_rpc_pipe_open(cli, transport, table, &result);
3160         if (!NT_STATUS_IS_OK(status)) {
3161                 return status;
3162         }
3163
3164         status = rpccli_generic_bind_data_from_creds(result,
3165                                                      auth_type, auth_level,
3166                                                      server, target_service,
3167                                                      creds,
3168                                                      &auth);
3169         if (!NT_STATUS_IS_OK(status)) {
3170                 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3171                           nt_errstr(status)));
3172                 goto err;
3173         }
3174
3175         status = rpc_pipe_bind(result, auth);
3176         if (!NT_STATUS_IS_OK(status)) {
3177                 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
3178                         nt_errstr(status) ));
3179                 goto err;
3180         }
3181
3182         DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
3183                 "machine %s and bound as user %s.\n", table->name,
3184                   result->desthost, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3185
3186         *presult = result;
3187         return NT_STATUS_OK;
3188
3189   err:
3190
3191         TALLOC_FREE(result);
3192         return status;
3193 }
3194
3195 /****************************************************************************
3196  Open a named pipe to an SMB server and bind using the mech specified
3197
3198  This routine steals the creds pointer that is passed in
3199  ****************************************************************************/
3200
3201 NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
3202                                         const struct ndr_interface_table *table,
3203                                         enum dcerpc_transport_t transport,
3204                                         enum credentials_use_kerberos use_kerberos,
3205                                         enum dcerpc_AuthType auth_type,
3206                                         enum dcerpc_AuthLevel auth_level,
3207                                         const char *server,
3208                                         const char *domain,
3209                                         const char *username,
3210                                         const char *password,
3211                                         struct rpc_pipe_client **presult)
3212 {
3213         struct rpc_pipe_client *result;
3214         struct pipe_auth_data *auth = NULL;
3215         const char *target_service = table->authservices->names[0];
3216         
3217         NTSTATUS status;
3218
3219         status = cli_rpc_pipe_open(cli, transport, table, &result);
3220         if (!NT_STATUS_IS_OK(status)) {
3221                 return status;
3222         }
3223
3224         status = rpccli_generic_bind_data(result,
3225                                           auth_type, auth_level,
3226                                           server, target_service,
3227                                           domain, username, password, 
3228                                           CRED_AUTO_USE_KERBEROS,
3229                                           NULL,
3230                                           &auth);
3231         if (!NT_STATUS_IS_OK(status)) {
3232                 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3233                           nt_errstr(status)));
3234                 goto err;
3235         }
3236
3237         status = rpc_pipe_bind(result, auth);
3238         if (!NT_STATUS_IS_OK(status)) {
3239                 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
3240                         nt_errstr(status) ));
3241                 goto err;
3242         }
3243
3244         DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
3245                 "machine %s and bound as user %s\\%s.\n", table->name,
3246                   result->desthost, domain, username));
3247
3248         *presult = result;
3249         return NT_STATUS_OK;
3250
3251   err:
3252
3253         TALLOC_FREE(result);
3254         return status;
3255 }
3256
3257 NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
3258                                                const struct ndr_interface_table *table,
3259                                                enum dcerpc_transport_t transport,
3260                                                struct cli_credentials *cli_creds,
3261                                                struct netlogon_creds_cli_context *netlogon_creds,
3262                                                struct rpc_pipe_client **_rpccli)
3263 {
3264         struct rpc_pipe_client *rpccli;
3265         struct pipe_auth_data *rpcauth;
3266         const char *target_service = table->authservices->names[0];
3267         struct netlogon_creds_CredentialState *ncreds = NULL;
3268         enum dcerpc_AuthLevel auth_level;
3269         NTSTATUS status;
3270         int rpc_pipe_bind_dbglvl = 0;
3271
3272         status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
3273         if (!NT_STATUS_IS_OK(status)) {
3274                 return status;
3275         }
3276
3277         status = netlogon_creds_cli_lock(netlogon_creds, rpccli, &ncreds);
3278         if (!NT_STATUS_IS_OK(status)) {
3279                 DEBUG(0, ("netlogon_creds_cli_get returned %s\n",
3280                           nt_errstr(status)));
3281                 TALLOC_FREE(rpccli);
3282                 return status;
3283         }
3284
3285         auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
3286
3287         cli_credentials_set_netlogon_creds(cli_creds, ncreds);
3288
3289         status = rpccli_generic_bind_data_from_creds(rpccli,
3290                                                      DCERPC_AUTH_TYPE_SCHANNEL,
3291                                                      auth_level,
3292                                                      rpccli->desthost,
3293                                                      target_service,
3294                                                      cli_creds,
3295                                                      &rpcauth);
3296         if (!NT_STATUS_IS_OK(status)) {
3297                 DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
3298                           nt_errstr(status)));
3299                 TALLOC_FREE(rpccli);
3300                 return status;
3301         }
3302
3303         status = rpc_pipe_bind(rpccli, rpcauth);
3304         cli_credentials_set_netlogon_creds(cli_creds, NULL);
3305         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3306                 rpc_pipe_bind_dbglvl = 1;
3307                 netlogon_creds_cli_delete(netlogon_creds, &ncreds);
3308         }
3309         if (!NT_STATUS_IS_OK(status)) {
3310                 DEBUG(rpc_pipe_bind_dbglvl,
3311                       ("%s: rpc_pipe_bind failed with error %s\n",
3312                        __func__, nt_errstr(status)));
3313                 TALLOC_FREE(rpccli);
3314                 return status;
3315         }
3316
3317         TALLOC_FREE(ncreds);
3318
3319         if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) {
3320                 goto done;
3321         }
3322
3323         status = netlogon_creds_cli_check(netlogon_creds,
3324                                           rpccli->binding_handle);
3325         if (!NT_STATUS_IS_OK(status)) {
3326                 DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
3327                           nt_errstr(status)));
3328                 TALLOC_FREE(rpccli);
3329                 return status;
3330         }
3331
3332
3333 done:
3334         DEBUG(10,("%s: opened pipe %s to machine %s "
3335                   "for domain %s and bound using schannel.\n",
3336                   __func__, table->name,
3337                   rpccli->desthost, cli_credentials_get_domain(cli_creds)));
3338
3339         *_rpccli = rpccli;
3340         return NT_STATUS_OK;
3341 }
3342
3343 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3344                              struct rpc_pipe_client *cli,
3345                              DATA_BLOB *session_key)
3346 {
3347         NTSTATUS status;
3348         struct pipe_auth_data *a;
3349         struct gensec_security *gensec_security;
3350         DATA_BLOB sk = data_blob_null;
3351         bool make_dup = false;
3352
3353         if (!session_key || !cli) {
3354                 return NT_STATUS_INVALID_PARAMETER;
3355         }
3356
3357         a = cli->auth;
3358
3359         if (a == NULL) {
3360                 return NT_STATUS_INVALID_PARAMETER;
3361         }
3362
3363         switch (cli->auth->auth_type) {
3364         case DCERPC_AUTH_TYPE_NONE:
3365                 sk = data_blob_const(a->transport_session_key.data,
3366                                      a->transport_session_key.length);
3367                 make_dup = true;
3368                 break;
3369         default:
3370                 gensec_security = a->auth_ctx;
3371                 status = gensec_session_key(gensec_security, mem_ctx, &sk);
3372                 if (!NT_STATUS_IS_OK(status)) {
3373                         return status;
3374                 }
3375                 make_dup = false;
3376                 break;
3377         }
3378
3379         if (!sk.data) {
3380                 return NT_STATUS_NO_USER_SESSION_KEY;
3381         }
3382
3383         if (make_dup) {
3384                 *session_key = data_blob_dup_talloc(mem_ctx, sk);
3385         } else {
3386                 *session_key = sk;
3387         }
3388
3389         return NT_STATUS_OK;
3390 }