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