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