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