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