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