rpc: Give dcerpc_util.c its own header
[samba.git] / source3 / rpc_client / cli_pipe.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client routines
4  *  Largely rewritten by Jeremy Allison             2005.
5  *  Heavily modified by Simo Sorce                  2010.
6  *  Copyright Andrew Bartlett                       2011.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23 #include "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 "librpc/rpc/dcerpc_util.h"
34 #include "rpc_dce.h"
35 #include "cli_pipe.h"
36 #include "libsmb/libsmb.h"
37 #include "auth/gensec/gensec.h"
38 #include "auth/credentials/credentials.h"
39 #include "../libcli/smb/smbXcli_base.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;
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;
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 blob
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         if (rpc_cli == NULL) {
2163                 return RPCCLI_DEFAULT_TIMEOUT;
2164         }
2165
2166         if (rpc_cli->binding_handle == NULL) {
2167                 return RPCCLI_DEFAULT_TIMEOUT;
2168         }
2169
2170         return dcerpc_binding_handle_set_timeout(rpc_cli->binding_handle,
2171                                                  timeout);
2172 }
2173
2174 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2175 {
2176         if (rpc_cli == NULL) {
2177                 return false;
2178         }
2179
2180         if (rpc_cli->binding_handle == NULL) {
2181                 return false;
2182         }
2183
2184         return dcerpc_binding_handle_is_connected(rpc_cli->binding_handle);
2185 }
2186
2187 struct rpccli_bh_state {
2188         struct rpc_pipe_client *rpc_cli;
2189 };
2190
2191 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2192 {
2193         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2194                                      struct rpccli_bh_state);
2195         struct rpc_cli_transport *transport = hs->rpc_cli->transport;
2196
2197         if (transport == NULL) {
2198                 return false;
2199         }
2200
2201         if (transport->is_connected == NULL) {
2202                 return false;
2203         }
2204
2205         return transport->is_connected(transport->priv);
2206 }
2207
2208 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2209                                       uint32_t timeout)
2210 {
2211         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2212                                      struct rpccli_bh_state);
2213         struct rpc_cli_transport *transport = hs->rpc_cli->transport;
2214         unsigned int old;
2215
2216         if (transport == NULL) {
2217                 return RPCCLI_DEFAULT_TIMEOUT;
2218         }
2219
2220         if (transport->set_timeout == NULL) {
2221                 return RPCCLI_DEFAULT_TIMEOUT;
2222         }
2223
2224         old = transport->set_timeout(transport->priv, timeout);
2225         if (old == 0) {
2226                 return RPCCLI_DEFAULT_TIMEOUT;
2227         }
2228
2229         return old;
2230 }
2231
2232 static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
2233                                 enum dcerpc_AuthType *auth_type,
2234                                 enum dcerpc_AuthLevel *auth_level)
2235 {
2236         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2237                                      struct rpccli_bh_state);
2238
2239         if (hs->rpc_cli == NULL) {
2240                 return;
2241         }
2242
2243         if (hs->rpc_cli->auth == NULL) {
2244                 return;
2245         }
2246
2247         *auth_type = hs->rpc_cli->auth->auth_type;
2248         *auth_level = hs->rpc_cli->auth->auth_level;
2249 }
2250
2251 struct rpccli_bh_raw_call_state {
2252         DATA_BLOB in_data;
2253         DATA_BLOB out_data;
2254         uint32_t out_flags;
2255 };
2256
2257 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2258
2259 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2260                                                   struct tevent_context *ev,
2261                                                   struct dcerpc_binding_handle *h,
2262                                                   const struct GUID *object,
2263                                                   uint32_t opnum,
2264                                                   uint32_t in_flags,
2265                                                   const uint8_t *in_data,
2266                                                   size_t in_length)
2267 {
2268         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2269                                      struct rpccli_bh_state);
2270         struct tevent_req *req;
2271         struct rpccli_bh_raw_call_state *state;
2272         bool ok;
2273         struct tevent_req *subreq;
2274
2275         req = tevent_req_create(mem_ctx, &state,
2276                                 struct rpccli_bh_raw_call_state);
2277         if (req == NULL) {
2278                 return NULL;
2279         }
2280         state->in_data.data = discard_const_p(uint8_t, in_data);
2281         state->in_data.length = in_length;
2282
2283         ok = rpccli_bh_is_connected(h);
2284         if (!ok) {
2285                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2286                 return tevent_req_post(req, ev);
2287         }
2288
2289         subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2290                                        opnum, object, &state->in_data);
2291         if (tevent_req_nomem(subreq, req)) {
2292                 return tevent_req_post(req, ev);
2293         }
2294         tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2295
2296         return req;
2297 }
2298
2299 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2300 {
2301         struct tevent_req *req =
2302                 tevent_req_callback_data(subreq,
2303                 struct tevent_req);
2304         struct rpccli_bh_raw_call_state *state =
2305                 tevent_req_data(req,
2306                 struct rpccli_bh_raw_call_state);
2307         NTSTATUS status;
2308
2309         state->out_flags = 0;
2310
2311         /* TODO: support bigendian responses */
2312
2313         status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2314         TALLOC_FREE(subreq);
2315         if (!NT_STATUS_IS_OK(status)) {
2316                 tevent_req_nterror(req, status);
2317                 return;
2318         }
2319
2320         tevent_req_done(req);
2321 }
2322
2323 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2324                                         TALLOC_CTX *mem_ctx,
2325                                         uint8_t **out_data,
2326                                         size_t *out_length,
2327                                         uint32_t *out_flags)
2328 {
2329         struct rpccli_bh_raw_call_state *state =
2330                 tevent_req_data(req,
2331                 struct rpccli_bh_raw_call_state);
2332         NTSTATUS status;
2333
2334         if (tevent_req_is_nterror(req, &status)) {
2335                 tevent_req_received(req);
2336                 return status;
2337         }
2338
2339         *out_data = talloc_move(mem_ctx, &state->out_data.data);
2340         *out_length = state->out_data.length;
2341         *out_flags = state->out_flags;
2342         tevent_req_received(req);
2343         return NT_STATUS_OK;
2344 }
2345
2346 struct rpccli_bh_disconnect_state {
2347         uint8_t _dummy;
2348 };
2349
2350 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2351                                                 struct tevent_context *ev,
2352                                                 struct dcerpc_binding_handle *h)
2353 {
2354         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2355                                      struct rpccli_bh_state);
2356         struct tevent_req *req;
2357         struct rpccli_bh_disconnect_state *state;
2358         bool ok;
2359
2360         req = tevent_req_create(mem_ctx, &state,
2361                                 struct rpccli_bh_disconnect_state);
2362         if (req == NULL) {
2363                 return NULL;
2364         }
2365
2366         ok = rpccli_bh_is_connected(h);
2367         if (!ok) {
2368                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2369                 return tevent_req_post(req, ev);
2370         }
2371
2372         /*
2373          * TODO: do a real async disconnect ...
2374          *
2375          * For now we do it sync...
2376          */
2377         TALLOC_FREE(hs->rpc_cli->transport);
2378         hs->rpc_cli = NULL;
2379
2380         tevent_req_done(req);
2381         return tevent_req_post(req, ev);
2382 }
2383
2384 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2385 {
2386         NTSTATUS status;
2387
2388         if (tevent_req_is_nterror(req, &status)) {
2389                 tevent_req_received(req);
2390                 return status;
2391         }
2392
2393         tevent_req_received(req);
2394         return NT_STATUS_OK;
2395 }
2396
2397 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2398 {
2399         return true;
2400 }
2401
2402 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2403                                    int ndr_flags,
2404                                    const void *_struct_ptr,
2405                                    const struct ndr_interface_call *call)
2406 {
2407         void *struct_ptr = discard_const(_struct_ptr);
2408
2409         if (DEBUGLEVEL < 10) {
2410                 return;
2411         }
2412
2413         if (ndr_flags & NDR_IN) {
2414                 ndr_print_function_debug(call->ndr_print,
2415                                          call->name,
2416                                          ndr_flags,
2417                                          struct_ptr);
2418         }
2419         if (ndr_flags & NDR_OUT) {
2420                 ndr_print_function_debug(call->ndr_print,
2421                                          call->name,
2422                                          ndr_flags,
2423                                          struct_ptr);
2424         }
2425 }
2426
2427 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2428         .name                   = "rpccli",
2429         .is_connected           = rpccli_bh_is_connected,
2430         .set_timeout            = rpccli_bh_set_timeout,
2431         .auth_info              = rpccli_bh_auth_info,
2432         .raw_call_send          = rpccli_bh_raw_call_send,
2433         .raw_call_recv          = rpccli_bh_raw_call_recv,
2434         .disconnect_send        = rpccli_bh_disconnect_send,
2435         .disconnect_recv        = rpccli_bh_disconnect_recv,
2436
2437         .ref_alloc              = rpccli_bh_ref_alloc,
2438         .do_ndr_print           = rpccli_bh_do_ndr_print,
2439 };
2440
2441 /* initialise a rpc_pipe_client binding handle */
2442 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2443                                         const struct GUID *object,
2444                                         const struct ndr_interface_table *table)
2445 {
2446         struct dcerpc_binding_handle *h;
2447         struct rpccli_bh_state *hs;
2448
2449         h = dcerpc_binding_handle_create(c,
2450                                          &rpccli_bh_ops,
2451                                          object,
2452                                          table,
2453                                          &hs,
2454                                          struct rpccli_bh_state,
2455                                          __location__);
2456         if (h == NULL) {
2457                 return NULL;
2458         }
2459         hs->rpc_cli = c;
2460
2461         return h;
2462 }
2463
2464 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2465                                struct pipe_auth_data **presult)
2466 {
2467         struct pipe_auth_data *result;
2468         struct auth_generic_state *auth_generic_ctx;
2469         NTSTATUS status;
2470
2471         result = talloc_zero(mem_ctx, struct pipe_auth_data);
2472         if (result == NULL) {
2473                 return NT_STATUS_NO_MEMORY;
2474         }
2475
2476         result->auth_type = DCERPC_AUTH_TYPE_NONE;
2477         result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2478         result->auth_context_id = 0;
2479
2480         status = auth_generic_client_prepare(result,
2481                                              &auth_generic_ctx);
2482         if (!NT_STATUS_IS_OK(status)) {
2483                 DEBUG(1, ("Failed to create auth_generic context: %s\n",
2484                           nt_errstr(status)));
2485         }
2486
2487         status = auth_generic_set_username(auth_generic_ctx, "");
2488         if (!NT_STATUS_IS_OK(status)) {
2489                 DEBUG(1, ("Failed to set username: %s\n",
2490                           nt_errstr(status)));
2491         }
2492
2493         status = auth_generic_set_domain(auth_generic_ctx, "");
2494         if (!NT_STATUS_IS_OK(status)) {
2495                 DEBUG(1, ("Failed to set domain: %s\n",
2496                           nt_errstr(status)));
2497                 return status;
2498         }
2499
2500         status = gensec_set_credentials(auth_generic_ctx->gensec_security,
2501                                         auth_generic_ctx->credentials);
2502         if (!NT_STATUS_IS_OK(status)) {
2503                 DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
2504                           nt_errstr(status)));
2505                 return status;
2506         }
2507         talloc_unlink(auth_generic_ctx, auth_generic_ctx->credentials);
2508         auth_generic_ctx->credentials = NULL;
2509
2510         result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2511         talloc_free(auth_generic_ctx);
2512         *presult = result;
2513         return NT_STATUS_OK;
2514 }
2515
2516 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2517                                          enum dcerpc_AuthType auth_type,
2518                                          enum dcerpc_AuthLevel auth_level,
2519                                          const char *server,
2520                                          const char *target_service,
2521                                          const char *domain,
2522                                          const char *username,
2523                                          const char *password,
2524                                          enum credentials_use_kerberos use_kerberos,
2525                                          struct netlogon_creds_CredentialState *creds,
2526                                          struct pipe_auth_data **presult)
2527 {
2528         struct auth_generic_state *auth_generic_ctx;
2529         struct pipe_auth_data *result;
2530         NTSTATUS status;
2531
2532         result = talloc_zero(mem_ctx, struct pipe_auth_data);
2533         if (result == NULL) {
2534                 return NT_STATUS_NO_MEMORY;
2535         }
2536
2537         result->auth_type = auth_type;
2538         result->auth_level = auth_level;
2539         result->auth_context_id = 1;
2540
2541         status = auth_generic_client_prepare(result,
2542                                              &auth_generic_ctx);
2543         if (!NT_STATUS_IS_OK(status)) {
2544                 goto fail;
2545         }
2546
2547         status = auth_generic_set_username(auth_generic_ctx, username);
2548         if (!NT_STATUS_IS_OK(status)) {
2549                 goto fail;
2550         }
2551
2552         status = auth_generic_set_domain(auth_generic_ctx, domain);
2553         if (!NT_STATUS_IS_OK(status)) {
2554                 goto fail;
2555         }
2556
2557         status = auth_generic_set_password(auth_generic_ctx, password);
2558         if (!NT_STATUS_IS_OK(status)) {
2559                 goto fail;
2560         }
2561
2562         status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2563         if (!NT_STATUS_IS_OK(status)) {
2564                 goto fail;
2565         }
2566
2567         status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2568         if (!NT_STATUS_IS_OK(status)) {
2569                 goto fail;
2570         }
2571
2572         cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos);
2573         cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
2574
2575         status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2576         if (!NT_STATUS_IS_OK(status)) {
2577                 goto fail;
2578         }
2579
2580         result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2581         talloc_free(auth_generic_ctx);
2582         *presult = result;
2583         return NT_STATUS_OK;
2584
2585  fail:
2586         TALLOC_FREE(result);
2587         return status;
2588 }
2589
2590 /* This routine steals the creds pointer that is passed in */
2591 static NTSTATUS rpccli_generic_bind_data_from_creds(TALLOC_CTX *mem_ctx,
2592                                                     enum dcerpc_AuthType auth_type,
2593                                                     enum dcerpc_AuthLevel auth_level,
2594                                                     const char *server,
2595                                                     const char *target_service,
2596                                                     struct cli_credentials *creds,
2597                                                     struct pipe_auth_data **presult)
2598 {
2599         struct auth_generic_state *auth_generic_ctx;
2600         struct pipe_auth_data *result;
2601         NTSTATUS status;
2602
2603         result = talloc_zero(mem_ctx, struct pipe_auth_data);
2604         if (result == NULL) {
2605                 return NT_STATUS_NO_MEMORY;
2606         }
2607
2608         result->auth_type = auth_type;
2609         result->auth_level = auth_level;
2610         result->auth_context_id = 1;
2611
2612         status = auth_generic_client_prepare(result,
2613                                              &auth_generic_ctx);
2614         if (!NT_STATUS_IS_OK(status)) {
2615                 goto fail;
2616         }
2617
2618         status = auth_generic_set_creds(auth_generic_ctx, creds);
2619         if (!NT_STATUS_IS_OK(status)) {
2620                 goto fail;
2621         }
2622
2623         status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2624         if (!NT_STATUS_IS_OK(status)) {
2625                 goto fail;
2626         }
2627
2628         status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2629         if (!NT_STATUS_IS_OK(status)) {
2630                 goto fail;
2631         }
2632
2633         status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2634         if (!NT_STATUS_IS_OK(status)) {
2635                 goto fail;
2636         }
2637
2638         result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2639         talloc_free(auth_generic_ctx);
2640         *presult = result;
2641         return NT_STATUS_OK;
2642
2643  fail:
2644         TALLOC_FREE(result);
2645         return status;
2646 }
2647
2648 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2649                                   struct pipe_auth_data **presult)
2650 {
2651         return rpccli_generic_bind_data(mem_ctx,
2652                                         DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
2653                                         DCERPC_AUTH_LEVEL_CONNECT,
2654                                         NULL, /* server */
2655                                         "host", /* target_service */
2656                                         NAME_NT_AUTHORITY, /* domain */
2657                                         "SYSTEM",
2658                                         NULL, /* password */
2659                                         CRED_USE_KERBEROS_DISABLED,
2660                                         NULL, /* netlogon_creds_CredentialState */
2661                                         presult);
2662 }
2663
2664 /**
2665  * Create an rpc pipe client struct, connecting to a tcp port.
2666  */
2667 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2668                                        const struct sockaddr_storage *ss_addr,
2669                                        uint16_t port,
2670                                        const struct ndr_interface_table *table,
2671                                        struct rpc_pipe_client **presult)
2672 {
2673         struct rpc_pipe_client *result;
2674         struct sockaddr_storage addr;
2675         NTSTATUS status;
2676         int fd;
2677
2678         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2679         if (result == NULL) {
2680                 return NT_STATUS_NO_MEMORY;
2681         }
2682
2683         result->abstract_syntax = table->syntax_id;
2684         result->transfer_syntax = ndr_transfer_syntax_ndr;
2685
2686         result->desthost = talloc_strdup(result, host);
2687         if (result->desthost == NULL) {
2688                 status = NT_STATUS_NO_MEMORY;
2689                 goto fail;
2690         }
2691
2692         result->srv_name_slash = talloc_asprintf_strupper_m(
2693                 result, "\\\\%s", result->desthost);
2694         if (result->srv_name_slash == NULL) {
2695                 status = NT_STATUS_NO_MEMORY;
2696                 goto fail;
2697         }
2698
2699         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2700
2701         if (ss_addr == NULL) {
2702                 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2703                         status = NT_STATUS_NOT_FOUND;
2704                         goto fail;
2705                 }
2706         } else {
2707                 addr = *ss_addr;
2708         }
2709
2710         status = open_socket_out(&addr, port, 60*1000, &fd);
2711         if (!NT_STATUS_IS_OK(status)) {
2712                 goto fail;
2713         }
2714         set_socket_options(fd, lp_socket_options());
2715
2716         status = rpc_transport_sock_init(result, fd, &result->transport);
2717         if (!NT_STATUS_IS_OK(status)) {
2718                 close(fd);
2719                 goto fail;
2720         }
2721
2722         result->transport->transport = NCACN_IP_TCP;
2723
2724         result->binding_handle = rpccli_bh_create(result, NULL, table);
2725         if (result->binding_handle == NULL) {
2726                 TALLOC_FREE(result);
2727                 return NT_STATUS_NO_MEMORY;
2728         }
2729
2730         *presult = result;
2731         return NT_STATUS_OK;
2732
2733  fail:
2734         TALLOC_FREE(result);
2735         return status;
2736 }
2737
2738 static NTSTATUS rpccli_epm_map_binding(
2739         struct dcerpc_binding_handle *epm_connection,
2740         struct dcerpc_binding *binding,
2741         TALLOC_CTX *mem_ctx,
2742         char **pendpoint)
2743 {
2744         TALLOC_CTX *frame = talloc_stackframe();
2745         enum dcerpc_transport_t transport =
2746                 dcerpc_binding_get_transport(binding);
2747         enum dcerpc_transport_t res_transport;
2748         struct dcerpc_binding *res_binding = NULL;
2749         struct epm_twr_t *map_tower = NULL;
2750         struct epm_twr_p_t res_towers = { .twr = NULL };
2751         struct policy_handle *entry_handle = NULL;
2752         uint32_t num_towers = 0;
2753         const uint32_t max_towers = 1;
2754         const char *endpoint = NULL;
2755         char *tmp = NULL;
2756         uint32_t result;
2757         NTSTATUS status;
2758
2759         map_tower = talloc_zero(frame, struct epm_twr_t);
2760         if (map_tower == NULL) {
2761                 goto nomem;
2762         }
2763
2764         status = dcerpc_binding_build_tower(
2765                 frame, binding, &(map_tower->tower));
2766         if (!NT_STATUS_IS_OK(status)) {
2767                 DBG_DEBUG("dcerpc_binding_build_tower failed: %s\n",
2768                           nt_errstr(status));
2769                 goto done;
2770         }
2771
2772         res_towers.twr = talloc_array(frame, struct epm_twr_t, max_towers);
2773         if (res_towers.twr == NULL) {
2774                 goto nomem;
2775         }
2776
2777         entry_handle = talloc_zero(frame, struct policy_handle);
2778         if (entry_handle == NULL) {
2779                 goto nomem;
2780         }
2781
2782         status = dcerpc_epm_Map(
2783                 epm_connection,
2784                 frame,
2785                 NULL,
2786                 map_tower,
2787                 entry_handle,
2788                 max_towers,
2789                 &num_towers,
2790                 &res_towers,
2791                 &result);
2792
2793         if (!NT_STATUS_IS_OK(status)) {
2794                 DBG_DEBUG("dcerpc_epm_Map failed: %s\n", nt_errstr(status));
2795                 goto done;
2796         }
2797
2798         if (result != EPMAPPER_STATUS_OK) {
2799                 DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32"\n", result);
2800                 status = NT_STATUS_NOT_FOUND;
2801                 goto done;
2802         }
2803
2804         if (num_towers != 1) {
2805                 DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32" towers\n",
2806                           num_towers);
2807                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2808                 goto done;
2809         }
2810
2811         status = dcerpc_binding_from_tower(
2812                 frame, &(res_towers.twr->tower), &res_binding);
2813         if (!NT_STATUS_IS_OK(status)) {
2814                 DBG_DEBUG("dcerpc_binding_from_tower failed: %s\n",
2815                           nt_errstr(status));
2816                 goto done;
2817         }
2818
2819         res_transport = dcerpc_binding_get_transport(res_binding);
2820         if (res_transport != transport) {
2821                 DBG_DEBUG("dcerpc_epm_Map returned transport %d, "
2822                           "expected %d\n",
2823                           (int)res_transport,
2824                           (int)transport);
2825                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2826                 goto done;
2827         }
2828
2829         endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
2830         if (endpoint == NULL) {
2831                 DBG_DEBUG("dcerpc_epm_Map returned no endpoint\n");
2832                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2833                 goto done;
2834         }
2835
2836         tmp = talloc_strdup(mem_ctx, endpoint);
2837         if (tmp == NULL) {
2838                 goto nomem;
2839         }
2840         *pendpoint = tmp;
2841
2842         status = NT_STATUS_OK;
2843         goto done;
2844
2845 nomem:
2846         status = NT_STATUS_NO_MEMORY;
2847 done:
2848         TALLOC_FREE(frame);
2849         return status;
2850 }
2851
2852 static NTSTATUS rpccli_epm_map_interface(
2853         struct dcerpc_binding_handle *epm_connection,
2854         enum dcerpc_transport_t transport,
2855         const struct ndr_syntax_id *iface,
2856         TALLOC_CTX *mem_ctx,
2857         char **pendpoint)
2858 {
2859         struct dcerpc_binding *binding = NULL;
2860         char *endpoint = NULL;
2861         NTSTATUS status;
2862
2863         status = dcerpc_parse_binding(mem_ctx, "", &binding);
2864         if (!NT_STATUS_IS_OK(status)) {
2865                 DBG_DEBUG("dcerpc_parse_binding failed: %s\n",
2866                           nt_errstr(status));
2867                 goto done;
2868         }
2869
2870         status = dcerpc_binding_set_transport(binding, transport);
2871         if (!NT_STATUS_IS_OK(status)) {
2872                 DBG_DEBUG("dcerpc_binding_set_transport failed: %s\n",
2873                           nt_errstr(status));
2874                 goto done;
2875         }
2876
2877         status = dcerpc_binding_set_abstract_syntax(binding, iface);
2878         if (!NT_STATUS_IS_OK(status)) {
2879                 DBG_DEBUG("dcerpc_binding_set_abstract_syntax failed: %s\n",
2880                           nt_errstr(status));
2881                 goto done;
2882         }
2883
2884         status = rpccli_epm_map_binding(
2885                 epm_connection, binding, mem_ctx, &endpoint);
2886         if (!NT_STATUS_IS_OK(status)) {
2887                 DBG_DEBUG("rpccli_epm_map_binding failed: %s\n",
2888                           nt_errstr(status));
2889                 goto done;
2890         }
2891         *pendpoint = endpoint;
2892
2893 done:
2894         TALLOC_FREE(binding);
2895         return status;
2896 }
2897
2898 /**
2899  * Determine the tcp port on which a dcerpc interface is listening
2900  * for the ncacn_ip_tcp transport via the endpoint mapper of the
2901  * target host.
2902  */
2903 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2904                                       const struct sockaddr_storage *addr,
2905                                       const struct ndr_interface_table *table,
2906                                       uint16_t *pport)
2907 {
2908         NTSTATUS status;
2909         struct rpc_pipe_client *epm_pipe = NULL;
2910         struct pipe_auth_data *auth = NULL;
2911         char *endpoint = NULL;
2912         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2913
2914         if (pport == NULL) {
2915                 status = NT_STATUS_INVALID_PARAMETER;
2916                 goto done;
2917         }
2918
2919         if (ndr_syntax_id_equal(&table->syntax_id,
2920                                 &ndr_table_epmapper.syntax_id)) {
2921                 *pport = 135;
2922                 status = NT_STATUS_OK;
2923                 goto done;
2924         }
2925
2926         /* open the connection to the endpoint mapper */
2927         status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2928                                         &ndr_table_epmapper,
2929                                         &epm_pipe);
2930
2931         if (!NT_STATUS_IS_OK(status)) {
2932                 goto done;
2933         }
2934
2935         status = rpccli_anon_bind_data(tmp_ctx, &auth);
2936         if (!NT_STATUS_IS_OK(status)) {
2937                 goto done;
2938         }
2939
2940         status = rpc_pipe_bind(epm_pipe, auth);
2941         if (!NT_STATUS_IS_OK(status)) {
2942                 goto done;
2943         }
2944
2945         status = rpccli_epm_map_interface(
2946                 epm_pipe->binding_handle,
2947                 NCACN_IP_TCP,
2948                 &table->syntax_id,
2949                 tmp_ctx,
2950                 &endpoint);
2951         if (!NT_STATUS_IS_OK(status)) {
2952                 DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
2953                           nt_errstr(status));
2954                 goto done;
2955         }
2956
2957         *pport = (uint16_t)atoi(endpoint);
2958
2959 done:
2960         TALLOC_FREE(tmp_ctx);
2961         return status;
2962 }
2963
2964 /**
2965  * Create a rpc pipe client struct, connecting to a host via tcp.
2966  * The port is determined by asking the endpoint mapper on the given
2967  * host.
2968  */
2969 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2970                            const struct sockaddr_storage *addr,
2971                            const struct ndr_interface_table *table,
2972                            struct rpc_pipe_client **presult)
2973 {
2974         NTSTATUS status;
2975         uint16_t port = 0;
2976
2977         status = rpc_pipe_get_tcp_port(host, addr, table, &port);
2978         if (!NT_STATUS_IS_OK(status)) {
2979                 return status;
2980         }
2981
2982         return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2983                                       table, presult);
2984 }
2985
2986 static NTSTATUS rpc_pipe_get_ncalrpc_name(
2987         const struct ndr_syntax_id *iface,
2988         TALLOC_CTX *mem_ctx,
2989         char **psocket_name)
2990 {
2991         TALLOC_CTX *frame = talloc_stackframe();
2992         struct rpc_pipe_client *epm_pipe = NULL;
2993         struct pipe_auth_data *auth = NULL;
2994         NTSTATUS status = NT_STATUS_OK;
2995         bool is_epm;
2996
2997         is_epm = ndr_syntax_id_equal(iface, &ndr_table_epmapper.syntax_id);
2998         if (is_epm) {
2999                 char *endpoint = talloc_strdup(mem_ctx, "EPMAPPER");
3000                 if (endpoint == NULL) {
3001                         status = NT_STATUS_NO_MEMORY;
3002                         goto done;
3003                 }
3004                 *psocket_name = endpoint;
3005                 goto done;
3006         }
3007
3008         status = rpc_pipe_open_ncalrpc(
3009                 frame, &ndr_table_epmapper, &epm_pipe);
3010         if (!NT_STATUS_IS_OK(status)) {
3011                 DBG_DEBUG("rpc_pipe_open_ncalrpc failed: %s\n",
3012                           nt_errstr(status));
3013                 goto done;
3014         }
3015
3016         status = rpccli_anon_bind_data(epm_pipe, &auth);
3017         if (!NT_STATUS_IS_OK(status)) {
3018                 DBG_DEBUG("rpccli_anon_bind_data failed: %s\n",
3019                           nt_errstr(status));
3020                 goto done;
3021         }
3022
3023         status = rpc_pipe_bind(epm_pipe, auth);
3024         if (!NT_STATUS_IS_OK(status)) {
3025                 DBG_DEBUG("rpc_pipe_bind failed: %s\n", nt_errstr(status));
3026                 goto done;
3027         }
3028
3029         status = rpccli_epm_map_interface(
3030                 epm_pipe->binding_handle,
3031                 NCALRPC,
3032                 iface,
3033                 mem_ctx,
3034                 psocket_name);
3035         if (!NT_STATUS_IS_OK(status)) {
3036                 DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
3037                           nt_errstr(status));
3038         }
3039
3040 done:
3041         TALLOC_FREE(frame);
3042         return status;
3043 }
3044
3045 /********************************************************************
3046  Create a rpc pipe client struct, connecting to a unix domain socket
3047  ********************************************************************/
3048 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx,
3049                                const struct ndr_interface_table *table,
3050                                struct rpc_pipe_client **presult)
3051 {
3052         char *socket_name = NULL;
3053         struct rpc_pipe_client *result;
3054         struct sockaddr_un addr = { .sun_family = AF_UNIX };
3055         socklen_t salen = sizeof(addr);
3056         int pathlen;
3057         NTSTATUS status;
3058         int fd = -1;
3059
3060         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3061         if (result == NULL) {
3062                 return NT_STATUS_NO_MEMORY;
3063         }
3064
3065         status = rpc_pipe_get_ncalrpc_name(
3066                 &table->syntax_id, result, &socket_name);
3067         if (!NT_STATUS_IS_OK(status)) {
3068                 DBG_DEBUG("rpc_pipe_get_ncalrpc_name failed: %s\n",
3069                           nt_errstr(status));
3070                 goto fail;
3071         }
3072
3073         pathlen = snprintf(
3074                 addr.sun_path,
3075                 sizeof(addr.sun_path),
3076                 "%s/%s",
3077                 lp_ncalrpc_dir(),
3078                 socket_name);
3079         if ((pathlen < 0) || ((size_t)pathlen >= sizeof(addr.sun_path))) {
3080                 DBG_DEBUG("socket_path for %s too long\n", socket_name);
3081                 status = NT_STATUS_NAME_TOO_LONG;
3082                 goto fail;
3083         }
3084         TALLOC_FREE(socket_name);
3085
3086         result->abstract_syntax = table->syntax_id;
3087         result->transfer_syntax = ndr_transfer_syntax_ndr;
3088
3089         result->desthost = get_myname(result);
3090         if (result->desthost == NULL) {
3091                 status = NT_STATUS_NO_MEMORY;
3092                 goto fail;
3093         }
3094
3095         result->srv_name_slash = talloc_asprintf_strupper_m(
3096                 result, "\\\\%s", result->desthost);
3097         if (result->srv_name_slash == NULL) {
3098                 status = NT_STATUS_NO_MEMORY;
3099                 goto fail;
3100         }
3101
3102         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3103
3104         fd = socket(AF_UNIX, SOCK_STREAM, 0);
3105         if (fd == -1) {
3106                 status = map_nt_error_from_unix(errno);
3107                 goto fail;
3108         }
3109
3110         if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
3111                 DBG_ERR("connect(%s) failed: %s\n",
3112                         addr.sun_path,
3113                         strerror(errno));
3114                 status = map_nt_error_from_unix(errno);
3115                 goto fail;
3116         }
3117
3118         status = rpc_transport_sock_init(result, fd, &result->transport);
3119         if (!NT_STATUS_IS_OK(status)) {
3120                 goto fail;
3121         }
3122         fd = -1;
3123
3124         result->transport->transport = NCALRPC;
3125
3126         result->binding_handle = rpccli_bh_create(result, NULL, table);
3127         if (result->binding_handle == NULL) {
3128                 status = NT_STATUS_NO_MEMORY;
3129                 goto fail;
3130         }
3131
3132         *presult = result;
3133         return NT_STATUS_OK;
3134
3135  fail:
3136         if (fd != -1) {
3137                 close(fd);
3138         }
3139         TALLOC_FREE(result);
3140         return status;
3141 }
3142
3143 struct rpc_pipe_client_np_ref {
3144         struct cli_state *cli;
3145         struct rpc_pipe_client *pipe;
3146 };
3147
3148 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3149 {
3150         DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3151         return 0;
3152 }
3153
3154 /****************************************************************************
3155  Open a named pipe over SMB to a remote server.
3156  *
3157  * CAVEAT CALLER OF THIS FUNCTION:
3158  *    The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3159  *    so be sure that this function is called AFTER any structure (vs pointer)
3160  *    assignment of the cli.  In particular, libsmbclient does structure
3161  *    assignments of cli, which invalidates the data in the returned
3162  *    rpc_pipe_client if this function is called before the structure assignment
3163  *    of cli.
3164  * 
3165  ****************************************************************************/
3166
3167 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3168                                  const struct ndr_interface_table *table,
3169                                  struct rpc_pipe_client **presult)
3170 {
3171         struct rpc_pipe_client *result;
3172         NTSTATUS status;
3173         struct rpc_pipe_client_np_ref *np_ref;
3174
3175         /* sanity check to protect against crashes */
3176
3177         if ( !cli ) {
3178                 return NT_STATUS_INVALID_HANDLE;
3179         }
3180
3181         result = talloc_zero(NULL, struct rpc_pipe_client);
3182         if (result == NULL) {
3183                 return NT_STATUS_NO_MEMORY;
3184         }
3185
3186         result->abstract_syntax = table->syntax_id;
3187         result->transfer_syntax = ndr_transfer_syntax_ndr;
3188
3189         result->desthost = talloc_strdup(
3190                 result, smbXcli_conn_remote_name(cli->conn));
3191         if (result->desthost == NULL) {
3192                 TALLOC_FREE(result);
3193                 return NT_STATUS_NO_MEMORY;
3194         }
3195
3196         result->srv_name_slash = talloc_asprintf_strupper_m(
3197                 result, "\\\\%s", result->desthost);
3198         if (result->srv_name_slash == NULL) {
3199                 TALLOC_FREE(result);
3200                 return NT_STATUS_NO_MEMORY;
3201         }
3202
3203         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3204
3205         status = rpc_transport_np_init(result, cli, table,
3206                                        &result->transport);
3207         if (!NT_STATUS_IS_OK(status)) {
3208                 TALLOC_FREE(result);
3209                 return status;
3210         }
3211
3212         result->transport->transport = NCACN_NP;
3213
3214         np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3215         if (np_ref == NULL) {
3216                 TALLOC_FREE(result);
3217                 return NT_STATUS_NO_MEMORY;
3218         }
3219         np_ref->cli = cli;
3220         np_ref->pipe = result;
3221
3222         DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3223         talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3224
3225         result->binding_handle = rpccli_bh_create(result, NULL, table);
3226         if (result->binding_handle == NULL) {
3227                 TALLOC_FREE(result);
3228                 return NT_STATUS_NO_MEMORY;
3229         }
3230
3231         *presult = result;
3232         return NT_STATUS_OK;
3233 }
3234
3235 /****************************************************************************
3236  Open a pipe to a remote server.
3237  ****************************************************************************/
3238
3239 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3240                                   enum dcerpc_transport_t transport,
3241                                   const struct ndr_interface_table *table,
3242                                   struct rpc_pipe_client **presult)
3243 {
3244         switch (transport) {
3245         case NCACN_IP_TCP:
3246                 return rpc_pipe_open_tcp(NULL,
3247                                          smbXcli_conn_remote_name(cli->conn),
3248                                          smbXcli_conn_remote_sockaddr(cli->conn),
3249                                          table, presult);
3250         case NCACN_NP:
3251                 return rpc_pipe_open_np(cli, table, presult);
3252         default:
3253                 return NT_STATUS_NOT_IMPLEMENTED;
3254         }
3255 }
3256
3257 /****************************************************************************
3258  Open a named pipe to an SMB server and bind anonymously.
3259  ****************************************************************************/
3260
3261 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3262                                             enum dcerpc_transport_t transport,
3263                                             const struct ndr_interface_table *table,
3264                                             struct rpc_pipe_client **presult)
3265 {
3266         struct rpc_pipe_client *result;
3267         struct pipe_auth_data *auth;
3268         NTSTATUS status;
3269
3270         status = cli_rpc_pipe_open(cli, transport, table, &result);
3271         if (!NT_STATUS_IS_OK(status)) {
3272                 return status;
3273         }
3274
3275         status = rpccli_anon_bind_data(result, &auth);
3276         if (!NT_STATUS_IS_OK(status)) {
3277                 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3278                           nt_errstr(status)));
3279                 TALLOC_FREE(result);
3280                 return status;
3281         }
3282
3283         /*
3284          * This is a bit of an abstraction violation due to the fact that an
3285          * anonymous bind on an authenticated SMB inherits the user/domain
3286          * from the enclosing SMB creds
3287          */
3288
3289         if (transport == NCACN_NP) {
3290                 struct smbXcli_session *session;
3291
3292                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3293                         session = cli->smb2.session;
3294                 } else {
3295                         session = cli->smb1.session;
3296                 }
3297
3298                 status = smbXcli_session_application_key(session, auth,
3299                                                 &auth->transport_session_key);
3300                 if (!NT_STATUS_IS_OK(status)) {
3301                         auth->transport_session_key = data_blob_null;
3302                 }
3303         }
3304
3305         status = rpc_pipe_bind(result, auth);
3306         if (!NT_STATUS_IS_OK(status)) {
3307                 int lvl = 0;
3308                 if (ndr_syntax_id_equal(&table->syntax_id,
3309                                         &ndr_table_dssetup.syntax_id)) {
3310                         /* non AD domains just don't have this pipe, avoid
3311                          * level 0 statement in that case - gd */
3312                         lvl = 3;
3313                 }
3314                 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3315                             "%s failed with error %s\n",
3316                             table->name,
3317                             nt_errstr(status) ));
3318                 TALLOC_FREE(result);
3319                 return status;
3320         }
3321
3322         DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3323                   "%s and bound anonymously.\n",
3324                   table->name,
3325                   result->desthost));
3326
3327         *presult = result;
3328         return NT_STATUS_OK;
3329 }
3330
3331 /****************************************************************************
3332  ****************************************************************************/
3333
3334 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3335                                   const struct ndr_interface_table *table,
3336                                   struct rpc_pipe_client **presult)
3337 {
3338         return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3339                                                   table, presult);
3340 }
3341
3342 /****************************************************************************
3343  Open a named pipe to an SMB server and bind using the mech specified
3344
3345  This routine references the creds pointer that is passed in
3346  ****************************************************************************/
3347
3348 NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
3349                                       const struct ndr_interface_table *table,
3350                                       enum dcerpc_transport_t transport,
3351                                       enum dcerpc_AuthType auth_type,
3352                                       enum dcerpc_AuthLevel auth_level,
3353                                       const char *server,
3354                                       struct cli_credentials *creds,
3355                                       struct rpc_pipe_client **presult)
3356 {
3357         struct rpc_pipe_client *result;
3358         struct pipe_auth_data *auth = NULL;
3359         const char *target_service = table->authservices->names[0];
3360         NTSTATUS status;
3361
3362         status = cli_rpc_pipe_open(cli, transport, table, &result);
3363         if (!NT_STATUS_IS_OK(status)) {
3364                 return status;
3365         }
3366
3367         status = rpccli_generic_bind_data_from_creds(result,
3368                                                      auth_type, auth_level,
3369                                                      server, target_service,
3370                                                      creds,
3371                                                      &auth);
3372         if (!NT_STATUS_IS_OK(status)) {
3373                 DBG_ERR("rpccli_generic_bind_data_from_creds returned %s\n",
3374                         nt_errstr(status));
3375                 goto err;
3376         }
3377
3378         status = rpc_pipe_bind(result, auth);
3379         if (!NT_STATUS_IS_OK(status)) {
3380                 DBG_ERR("cli_rpc_pipe_bind failed with error %s\n",
3381                         nt_errstr(status));
3382                 goto err;
3383         }
3384
3385         DBG_DEBUG("opened pipe %s to machine %s and bound as user %s.\n",
3386                   table->name,
3387                   result->desthost,
3388                   cli_credentials_get_unparsed_name(creds, talloc_tos()));
3389
3390         *presult = result;
3391         return NT_STATUS_OK;
3392
3393   err:
3394
3395         TALLOC_FREE(result);
3396         return status;
3397 }
3398
3399 NTSTATUS cli_rpc_pipe_open_bind_schannel(
3400         struct cli_state *cli,
3401         const struct ndr_interface_table *table,
3402         enum dcerpc_transport_t transport,
3403         struct netlogon_creds_cli_context *netlogon_creds,
3404         struct rpc_pipe_client **_rpccli)
3405 {
3406         struct rpc_pipe_client *rpccli;
3407         struct pipe_auth_data *rpcauth;
3408         const char *target_service = table->authservices->names[0];
3409         struct cli_credentials *cli_creds;
3410         enum dcerpc_AuthLevel auth_level;
3411         NTSTATUS status;
3412
3413         status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
3414         if (!NT_STATUS_IS_OK(status)) {
3415                 return status;
3416         }
3417
3418         auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
3419
3420         status = netlogon_creds_bind_cli_credentials(
3421                 netlogon_creds, rpccli, &cli_creds);
3422         if (!NT_STATUS_IS_OK(status)) {
3423                 DBG_DEBUG("netlogon_creds_bind_cli_credentials failed: %s\n",
3424                           nt_errstr(status));
3425                 TALLOC_FREE(rpccli);
3426                 return status;
3427         }
3428
3429         status = rpccli_generic_bind_data_from_creds(rpccli,
3430                                                      DCERPC_AUTH_TYPE_SCHANNEL,
3431                                                      auth_level,
3432                                                      rpccli->desthost,
3433                                                      target_service,
3434                                                      cli_creds,
3435                                                      &rpcauth);
3436         if (!NT_STATUS_IS_OK(status)) {
3437                 DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
3438                           nt_errstr(status)));
3439                 TALLOC_FREE(rpccli);
3440                 return status;
3441         }
3442
3443         status = rpc_pipe_bind(rpccli, rpcauth);
3444
3445         /* No TALLOC_FREE, gensec takes references */
3446         talloc_unlink(rpccli, cli_creds);
3447         cli_creds = NULL;
3448
3449         if (!NT_STATUS_IS_OK(status)) {
3450                 DBG_DEBUG("rpc_pipe_bind failed with error %s\n",
3451                           nt_errstr(status));
3452                 TALLOC_FREE(rpccli);
3453                 return status;
3454         }
3455
3456         *_rpccli = rpccli;
3457
3458         return NT_STATUS_OK;
3459 }
3460
3461 NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
3462                                                const struct ndr_interface_table *table,
3463                                                enum dcerpc_transport_t transport,
3464                                                struct netlogon_creds_cli_context *netlogon_creds,
3465                                                struct rpc_pipe_client **_rpccli)
3466 {
3467         TALLOC_CTX *frame = talloc_stackframe();
3468         struct rpc_pipe_client *rpccli;
3469         struct netlogon_creds_cli_lck *lck;
3470         NTSTATUS status;
3471
3472         status = netlogon_creds_cli_lck(
3473                 netlogon_creds, NETLOGON_CREDS_CLI_LCK_EXCLUSIVE,
3474                 frame, &lck);
3475         if (!NT_STATUS_IS_OK(status)) {
3476                 DBG_WARNING("netlogon_creds_cli_lck returned %s\n",
3477                             nt_errstr(status));
3478                 TALLOC_FREE(frame);
3479                 return status;
3480         }
3481
3482         status = cli_rpc_pipe_open_bind_schannel(
3483                 cli, table, transport, netlogon_creds, &rpccli);
3484         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3485                 netlogon_creds_cli_delete_lck(netlogon_creds);
3486         }
3487         if (!NT_STATUS_IS_OK(status)) {
3488                 DBG_DEBUG("cli_rpc_pipe_open_bind_schannel failed: %s\n",
3489                           nt_errstr(status));
3490                 TALLOC_FREE(frame);
3491                 return status;
3492         }
3493
3494         if (ndr_syntax_id_equal(&table->syntax_id,
3495                                 &ndr_table_netlogon.syntax_id)) {
3496                 status = netlogon_creds_cli_check(netlogon_creds,
3497                                                   rpccli->binding_handle,
3498                                                   NULL);
3499                 if (!NT_STATUS_IS_OK(status)) {
3500                         DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
3501                                   nt_errstr(status)));
3502                         TALLOC_FREE(frame);
3503                         return status;
3504                 }
3505         }
3506
3507         DBG_DEBUG("opened pipe %s to machine %s with key %s "
3508                   "and bound using schannel.\n",
3509                   table->name, rpccli->desthost,
3510                   netlogon_creds_cli_debug_string(netlogon_creds, lck));
3511
3512         TALLOC_FREE(frame);
3513
3514         *_rpccli = rpccli;
3515         return NT_STATUS_OK;
3516 }
3517
3518 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3519                              struct rpc_pipe_client *cli,
3520                              DATA_BLOB *session_key)
3521 {
3522         NTSTATUS status;
3523         struct pipe_auth_data *a;
3524         struct gensec_security *gensec_security;
3525         DATA_BLOB sk = data_blob_null;
3526         bool make_dup = false;
3527
3528         if (!session_key || !cli) {
3529                 return NT_STATUS_INVALID_PARAMETER;
3530         }
3531
3532         a = cli->auth;
3533
3534         if (a == NULL) {
3535                 return NT_STATUS_INVALID_PARAMETER;
3536         }
3537
3538         switch (cli->auth->auth_type) {
3539         case DCERPC_AUTH_TYPE_NONE:
3540                 sk = data_blob_const(a->transport_session_key.data,
3541                                      a->transport_session_key.length);
3542                 make_dup = true;
3543                 break;
3544         default:
3545                 gensec_security = a->auth_ctx;
3546                 status = gensec_session_key(gensec_security, mem_ctx, &sk);
3547                 if (!NT_STATUS_IS_OK(status)) {
3548                         return status;
3549                 }
3550                 make_dup = false;
3551                 break;
3552         }
3553
3554         if (!sk.data) {
3555                 return NT_STATUS_NO_USER_SESSION_KEY;
3556         }
3557
3558         if (make_dup) {
3559                 *session_key = data_blob_dup_talloc(mem_ctx, sk);
3560         } else {
3561                 *session_key = sk;
3562         }
3563
3564         return NT_STATUS_OK;
3565 }