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