s3:rpc_client: pass everything to gensec by default
[obnox/samba/samba-obnox.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 get_rpc_call_id(void)
60 {
61         static uint32 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 = talloc_get_type_abort(cli->auth->auth_ctx,
1011                                         struct gensec_security);
1012
1013         DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
1014         status = gensec_update(gensec_security, mem_ctx, null_blob, auth_token);
1015
1016         if (!NT_STATUS_IS_OK(status) &&
1017             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1018         {
1019                 return status;
1020         }
1021
1022         if (client_hdr_signing == NULL) {
1023                 return status;
1024         }
1025
1026         if (cli->auth->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1027                 *client_hdr_signing = false;
1028                 return status;
1029         }
1030
1031         *client_hdr_signing = gensec_have_feature(gensec_security,
1032                                                 GENSEC_FEATURE_SIGN_PKT_HEADER);
1033
1034         return status;
1035 }
1036
1037 /*******************************************************************
1038  Creates the internals of a DCE/RPC bind request or alter context PDU.
1039  ********************************************************************/
1040
1041 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1042                                                 enum dcerpc_pkt_type ptype,
1043                                                 uint32 rpc_call_id,
1044                                                 const struct ndr_syntax_id *abstract,
1045                                                 const struct ndr_syntax_id *transfer,
1046                                                 const DATA_BLOB *auth_info,
1047                                                 bool client_hdr_signing,
1048                                                 DATA_BLOB *blob)
1049 {
1050         uint16 auth_len = auth_info->length;
1051         NTSTATUS status;
1052         union dcerpc_payload u;
1053         struct dcerpc_ctx_list ctx_list;
1054         uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1055
1056         if (auth_len) {
1057                 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1058         }
1059
1060         if (client_hdr_signing) {
1061                 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1062         }
1063
1064         ctx_list.context_id = 0;
1065         ctx_list.num_transfer_syntaxes = 1;
1066         ctx_list.abstract_syntax = *abstract;
1067         ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1068
1069         u.bind.max_xmit_frag    = RPC_MAX_PDU_FRAG_LEN;
1070         u.bind.max_recv_frag    = RPC_MAX_PDU_FRAG_LEN;
1071         u.bind.assoc_group_id   = 0x0;
1072         u.bind.num_contexts     = 1;
1073         u.bind.ctx_list         = &ctx_list;
1074         u.bind.auth_info        = *auth_info;
1075
1076         status = dcerpc_push_ncacn_packet(mem_ctx,
1077                                           ptype, pfc_flags,
1078                                           auth_len,
1079                                           rpc_call_id,
1080                                           &u,
1081                                           blob);
1082         if (!NT_STATUS_IS_OK(status)) {
1083                 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1084                 return status;
1085         }
1086
1087         return NT_STATUS_OK;
1088 }
1089
1090 /*******************************************************************
1091  Creates a DCE/RPC bind request.
1092  ********************************************************************/
1093
1094 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1095                                     struct rpc_pipe_client *cli,
1096                                     struct pipe_auth_data *auth,
1097                                     uint32 rpc_call_id,
1098                                     const struct ndr_syntax_id *abstract,
1099                                     const struct ndr_syntax_id *transfer,
1100                                     DATA_BLOB *rpc_out)
1101 {
1102         DATA_BLOB auth_token = data_blob_null;
1103         DATA_BLOB auth_info = data_blob_null;
1104         NTSTATUS ret = NT_STATUS_OK;
1105
1106         switch (auth->auth_type) {
1107         case DCERPC_AUTH_TYPE_NONE:
1108                 break;
1109
1110         case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1111                 auth_token = data_blob_talloc(mem_ctx,
1112                                               "NCALRPC_AUTH_TOKEN",
1113                                               18);
1114                 break;
1115
1116         default:
1117                 ret = create_generic_auth_rpc_bind_req(cli, mem_ctx,
1118                                                        &auth_token,
1119                                                        &auth->client_hdr_signing);
1120
1121                 if (!NT_STATUS_IS_OK(ret) &&
1122                     !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1123                         return ret;
1124                 }
1125                 break;
1126         }
1127
1128         if (auth_token.length != 0) {
1129                 ret = dcerpc_push_dcerpc_auth(cli,
1130                                                 auth->auth_type,
1131                                                 auth->auth_level,
1132                                                 0, /* auth_pad_length */
1133                                                 1, /* auth_context_id */
1134                                                 &auth_token,
1135                                                 &auth_info);
1136                 if (!NT_STATUS_IS_OK(ret)) {
1137                         return ret;
1138                 }
1139                 data_blob_free(&auth_token);
1140         }
1141
1142         ret = create_bind_or_alt_ctx_internal(mem_ctx,
1143                                               DCERPC_PKT_BIND,
1144                                               rpc_call_id,
1145                                               abstract,
1146                                               transfer,
1147                                               &auth_info,
1148                                               auth->client_hdr_signing,
1149                                               rpc_out);
1150         return ret;
1151 }
1152
1153 /*******************************************************************
1154  External interface.
1155  Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1156  Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1157  and deals with signing/sealing details.
1158  ********************************************************************/
1159
1160 struct rpc_api_pipe_req_state {
1161         struct tevent_context *ev;
1162         struct rpc_pipe_client *cli;
1163         uint8_t op_num;
1164         uint32_t call_id;
1165         const DATA_BLOB *req_data;
1166         uint32_t req_data_sent;
1167         DATA_BLOB req_trailer;
1168         uint32_t req_trailer_sent;
1169         bool verify_bitmask1;
1170         bool verify_pcontext;
1171         DATA_BLOB rpc_out;
1172         DATA_BLOB reply_pdu;
1173 };
1174
1175 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1176 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1177 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state);
1178 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1179                                   bool *is_last_frag);
1180
1181 static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1182                                          struct tevent_context *ev,
1183                                          struct rpc_pipe_client *cli,
1184                                          uint8_t op_num,
1185                                          const DATA_BLOB *req_data)
1186 {
1187         struct tevent_req *req, *subreq;
1188         struct rpc_api_pipe_req_state *state;
1189         NTSTATUS status;
1190         bool is_last_frag;
1191
1192         req = tevent_req_create(mem_ctx, &state,
1193                                 struct rpc_api_pipe_req_state);
1194         if (req == NULL) {
1195                 return NULL;
1196         }
1197         state->ev = ev;
1198         state->cli = cli;
1199         state->op_num = op_num;
1200         state->req_data = req_data;
1201         state->req_data_sent = 0;
1202         state->call_id = get_rpc_call_id();
1203         state->reply_pdu = data_blob_null;
1204         state->rpc_out = data_blob_null;
1205
1206         if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1207                                         + RPC_MAX_SIGN_SIZE) {
1208                 /* Server is screwed up ! */
1209                 status = NT_STATUS_INVALID_PARAMETER;
1210                 goto post_status;
1211         }
1212
1213         status = prepare_verification_trailer(state);
1214         if (!NT_STATUS_IS_OK(status)) {
1215                 goto post_status;
1216         }
1217
1218         status = prepare_next_frag(state, &is_last_frag);
1219         if (!NT_STATUS_IS_OK(status)) {
1220                 goto post_status;
1221         }
1222
1223         if (is_last_frag) {
1224                 subreq = rpc_api_pipe_send(state, ev, state->cli,
1225                                            &state->rpc_out,
1226                                            DCERPC_PKT_RESPONSE,
1227                                            state->call_id);
1228                 if (subreq == NULL) {
1229                         goto fail;
1230                 }
1231                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1232         } else {
1233                 subreq = rpc_write_send(state, ev, cli->transport,
1234                                         state->rpc_out.data,
1235                                         state->rpc_out.length);
1236                 if (subreq == NULL) {
1237                         goto fail;
1238                 }
1239                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1240                                         req);
1241         }
1242         return req;
1243
1244  post_status:
1245         tevent_req_nterror(req, status);
1246         return tevent_req_post(req, ev);
1247  fail:
1248         TALLOC_FREE(req);
1249         return NULL;
1250 }
1251
1252 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state)
1253 {
1254         struct pipe_auth_data *a = state->cli->auth;
1255         struct dcerpc_sec_verification_trailer *t;
1256         struct dcerpc_sec_vt *c = NULL;
1257         struct ndr_push *ndr = NULL;
1258         enum ndr_err_code ndr_err;
1259         size_t align = 0;
1260         size_t pad = 0;
1261
1262         if (a == NULL) {
1263                 return NT_STATUS_OK;
1264         }
1265
1266         if (a->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1267                 return NT_STATUS_OK;
1268         }
1269
1270         t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1271         if (t == NULL) {
1272                 return NT_STATUS_NO_MEMORY;
1273         }
1274
1275         if (!a->verified_bitmask1) {
1276                 t->commands = talloc_realloc(t, t->commands,
1277                                              struct dcerpc_sec_vt,
1278                                              t->count.count + 1);
1279                 if (t->commands == NULL) {
1280                         return NT_STATUS_NO_MEMORY;
1281                 }
1282                 c = &t->commands[t->count.count++];
1283                 ZERO_STRUCTP(c);
1284
1285                 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1286                 if (a->client_hdr_signing) {
1287                         c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1288                 }
1289                 state->verify_bitmask1 = true;
1290         }
1291
1292         if (!state->cli->verified_pcontext) {
1293                 t->commands = talloc_realloc(t, t->commands,
1294                                              struct dcerpc_sec_vt,
1295                                              t->count.count + 1);
1296                 if (t->commands == NULL) {
1297                         return NT_STATUS_NO_MEMORY;
1298                 }
1299                 c = &t->commands[t->count.count++];
1300                 ZERO_STRUCTP(c);
1301
1302                 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1303                 c->u.pcontext.abstract_syntax = state->cli->abstract_syntax;
1304                 c->u.pcontext.transfer_syntax = state->cli->transfer_syntax;
1305
1306                 state->verify_pcontext = true;
1307         }
1308
1309         if (!a->hdr_signing) {
1310                 t->commands = talloc_realloc(t, t->commands,
1311                                              struct dcerpc_sec_vt,
1312                                              t->count.count + 1);
1313                 if (t->commands == NULL) {
1314                         return NT_STATUS_NO_MEMORY;
1315                 }
1316                 c = &t->commands[t->count.count++];
1317                 ZERO_STRUCTP(c);
1318
1319                 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1320                 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1321                 c->u.header2.drep[0] = DCERPC_DREP_LE;
1322                 c->u.header2.drep[1] = 0;
1323                 c->u.header2.drep[2] = 0;
1324                 c->u.header2.drep[3] = 0;
1325                 c->u.header2.call_id = state->call_id;
1326                 c->u.header2.context_id = 0;
1327                 c->u.header2.opnum = state->op_num;
1328         }
1329
1330         if (t->count.count == 0) {
1331                 TALLOC_FREE(t);
1332                 return NT_STATUS_OK;
1333         }
1334
1335         c = &t->commands[t->count.count - 1];
1336         c->command |= DCERPC_SEC_VT_COMMAND_END;
1337
1338         if (DEBUGLEVEL >= 10) {
1339                 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1340         }
1341
1342         ndr = ndr_push_init_ctx(state);
1343         if (ndr == NULL) {
1344                 return NT_STATUS_NO_MEMORY;
1345         }
1346
1347         ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1348                                                 NDR_SCALARS | NDR_BUFFERS,
1349                                                 t);
1350         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1351                 return ndr_map_error2ntstatus(ndr_err);
1352         }
1353         state->req_trailer = ndr_push_blob(ndr);
1354
1355         align = state->req_data->length & 0x3;
1356         if (align > 0) {
1357                 pad = 4 - align;
1358         }
1359         if (pad > 0) {
1360                 bool ok;
1361                 uint8_t *p;
1362                 const uint8_t zeros[4] = { 0, };
1363
1364                 ok = data_blob_append(ndr, &state->req_trailer, zeros, pad);
1365                 if (!ok) {
1366                         return NT_STATUS_NO_MEMORY;
1367                 }
1368
1369                 /* move the padding to the start */
1370                 p = state->req_trailer.data;
1371                 memmove(p + pad, p, state->req_trailer.length - pad);
1372                 memset(p, 0, pad);
1373         }
1374
1375         return NT_STATUS_OK;
1376 }
1377
1378 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1379                                   bool *is_last_frag)
1380 {
1381         size_t auth_len;
1382         size_t frag_len;
1383         uint8_t flags = 0;
1384         size_t pad_len;
1385         size_t data_left;
1386         size_t data_thistime;
1387         size_t trailer_left;
1388         size_t trailer_thistime = 0;
1389         size_t total_left;
1390         size_t total_thistime;
1391         NTSTATUS status;
1392         bool ok;
1393         union dcerpc_payload u;
1394
1395         data_left = state->req_data->length - state->req_data_sent;
1396         trailer_left = state->req_trailer.length - state->req_trailer_sent;
1397         total_left = data_left + trailer_left;
1398         if ((total_left < data_left) || (total_left < trailer_left)) {
1399                 /*
1400                  * overflow
1401                  */
1402                 return NT_STATUS_INVALID_PARAMETER_MIX;
1403         }
1404
1405         status = dcerpc_guess_sizes(state->cli->auth,
1406                                     DCERPC_REQUEST_LENGTH, total_left,
1407                                     state->cli->max_xmit_frag,
1408                                     CLIENT_NDR_PADDING_SIZE,
1409                                     &total_thistime,
1410                                     &frag_len, &auth_len, &pad_len);
1411         if (!NT_STATUS_IS_OK(status)) {
1412                 return status;
1413         }
1414
1415         if (state->req_data_sent == 0) {
1416                 flags = DCERPC_PFC_FLAG_FIRST;
1417         }
1418
1419         if (total_thistime == total_left) {
1420                 flags |= DCERPC_PFC_FLAG_LAST;
1421         }
1422
1423         data_thistime = MIN(total_thistime, data_left);
1424         if (data_thistime < total_thistime) {
1425                 trailer_thistime = total_thistime - data_thistime;
1426         }
1427
1428         data_blob_free(&state->rpc_out);
1429
1430         ZERO_STRUCT(u.request);
1431
1432         u.request.alloc_hint    = total_left;
1433         u.request.context_id    = 0;
1434         u.request.opnum         = state->op_num;
1435
1436         status = dcerpc_push_ncacn_packet(state,
1437                                           DCERPC_PKT_REQUEST,
1438                                           flags,
1439                                           auth_len,
1440                                           state->call_id,
1441                                           &u,
1442                                           &state->rpc_out);
1443         if (!NT_STATUS_IS_OK(status)) {
1444                 return status;
1445         }
1446
1447         /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1448          * compute it right for requests because the auth trailer is missing
1449          * at this stage */
1450         dcerpc_set_frag_length(&state->rpc_out, frag_len);
1451
1452         if (data_thistime > 0) {
1453                 /* Copy in the data. */
1454                 ok = data_blob_append(NULL, &state->rpc_out,
1455                                 state->req_data->data + state->req_data_sent,
1456                                 data_thistime);
1457                 if (!ok) {
1458                         return NT_STATUS_NO_MEMORY;
1459                 }
1460                 state->req_data_sent += data_thistime;
1461         }
1462
1463         if (trailer_thistime > 0) {
1464                 /* Copy in the verification trailer. */
1465                 ok = data_blob_append(NULL, &state->rpc_out,
1466                                 state->req_trailer.data + state->req_trailer_sent,
1467                                 trailer_thistime);
1468                 if (!ok) {
1469                         return NT_STATUS_NO_MEMORY;
1470                 }
1471                 state->req_trailer_sent += trailer_thistime;
1472         }
1473
1474         switch (state->cli->auth->auth_level) {
1475         case DCERPC_AUTH_LEVEL_NONE:
1476         case DCERPC_AUTH_LEVEL_CONNECT:
1477         case DCERPC_AUTH_LEVEL_PACKET:
1478                 break;
1479         case DCERPC_AUTH_LEVEL_INTEGRITY:
1480         case DCERPC_AUTH_LEVEL_PRIVACY:
1481                 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1482                                                 &state->rpc_out);
1483                 if (!NT_STATUS_IS_OK(status)) {
1484                         return status;
1485                 }
1486                 break;
1487         default:
1488                 return NT_STATUS_INVALID_PARAMETER;
1489         }
1490
1491         *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1492
1493         return status;
1494 }
1495
1496 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1497 {
1498         struct tevent_req *req = tevent_req_callback_data(
1499                 subreq, struct tevent_req);
1500         struct rpc_api_pipe_req_state *state = tevent_req_data(
1501                 req, struct rpc_api_pipe_req_state);
1502         NTSTATUS status;
1503         bool is_last_frag;
1504
1505         status = rpc_write_recv(subreq);
1506         TALLOC_FREE(subreq);
1507         if (!NT_STATUS_IS_OK(status)) {
1508                 tevent_req_nterror(req, status);
1509                 return;
1510         }
1511
1512         status = prepare_next_frag(state, &is_last_frag);
1513         if (!NT_STATUS_IS_OK(status)) {
1514                 tevent_req_nterror(req, status);
1515                 return;
1516         }
1517
1518         if (is_last_frag) {
1519                 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1520                                            &state->rpc_out,
1521                                            DCERPC_PKT_RESPONSE,
1522                                            state->call_id);
1523                 if (tevent_req_nomem(subreq, req)) {
1524                         return;
1525                 }
1526                 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1527         } else {
1528                 subreq = rpc_write_send(state, state->ev,
1529                                         state->cli->transport,
1530                                         state->rpc_out.data,
1531                                         state->rpc_out.length);
1532                 if (tevent_req_nomem(subreq, req)) {
1533                         return;
1534                 }
1535                 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1536                                         req);
1537         }
1538 }
1539
1540 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1541 {
1542         struct tevent_req *req = tevent_req_callback_data(
1543                 subreq, struct tevent_req);
1544         struct rpc_api_pipe_req_state *state = tevent_req_data(
1545                 req, struct rpc_api_pipe_req_state);
1546         NTSTATUS status;
1547
1548         status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1549         TALLOC_FREE(subreq);
1550         if (!NT_STATUS_IS_OK(status)) {
1551                 tevent_req_nterror(req, status);
1552                 return;
1553         }
1554
1555         if (state->cli->auth == NULL) {
1556                 tevent_req_done(req);
1557                 return;
1558         }
1559
1560         if (state->verify_bitmask1) {
1561                 state->cli->auth->verified_bitmask1 = true;
1562         }
1563
1564         if (state->verify_pcontext) {
1565                 state->cli->verified_pcontext = true;
1566         }
1567
1568         tevent_req_done(req);
1569 }
1570
1571 static NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1572                                DATA_BLOB *reply_pdu)
1573 {
1574         struct rpc_api_pipe_req_state *state = tevent_req_data(
1575                 req, struct rpc_api_pipe_req_state);
1576         NTSTATUS status;
1577
1578         if (tevent_req_is_nterror(req, &status)) {
1579                 /*
1580                  * We always have to initialize to reply pdu, even if there is
1581                  * none. The rpccli_* caller routines expect this.
1582                  */
1583                 *reply_pdu = data_blob_null;
1584                 return status;
1585         }
1586
1587         /* return data to caller and assign it ownership of memory */
1588         reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1589         reply_pdu->length = state->reply_pdu.length;
1590         state->reply_pdu.length = 0;
1591
1592         return NT_STATUS_OK;
1593 }
1594
1595 /****************************************************************************
1596  Check the rpc bind acknowledge response.
1597 ****************************************************************************/
1598
1599 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1600                                 const struct ndr_syntax_id *transfer)
1601 {
1602         struct dcerpc_ack_ctx ctx;
1603
1604         if (r->secondary_address_size == 0) {
1605                 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1606         }
1607
1608         if (r->num_results < 1 || !r->ctx_list) {
1609                 return false;
1610         }
1611
1612         ctx = r->ctx_list[0];
1613
1614         /* check the transfer syntax */
1615         if ((ctx.syntax.if_version != transfer->if_version) ||
1616              (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1617                 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1618                 return False;
1619         }
1620
1621         if (r->num_results != 0x1 || ctx.result != 0) {
1622                 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1623                           r->num_results, ctx.reason.value));
1624         }
1625
1626         DEBUG(5,("check_bind_response: accepted!\n"));
1627         return True;
1628 }
1629
1630 /*******************************************************************
1631  Creates a DCE/RPC bind authentication response.
1632  This is the packet that is sent back to the server once we
1633  have received a BIND-ACK, to finish the third leg of
1634  the authentication handshake.
1635  ********************************************************************/
1636
1637 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1638                                 struct rpc_pipe_client *cli,
1639                                 uint32 rpc_call_id,
1640                                 enum dcerpc_AuthType auth_type,
1641                                 enum dcerpc_AuthLevel auth_level,
1642                                 DATA_BLOB *pauth_blob,
1643                                 DATA_BLOB *rpc_out)
1644 {
1645         NTSTATUS status;
1646         union dcerpc_payload u;
1647
1648         u.auth3._pad = 0;
1649
1650         status = dcerpc_push_dcerpc_auth(mem_ctx,
1651                                          auth_type,
1652                                          auth_level,
1653                                          0, /* auth_pad_length */
1654                                          1, /* auth_context_id */
1655                                          pauth_blob,
1656                                          &u.auth3.auth_info);
1657         if (!NT_STATUS_IS_OK(status)) {
1658                 return status;
1659         }
1660
1661         status = dcerpc_push_ncacn_packet(mem_ctx,
1662                                           DCERPC_PKT_AUTH3,
1663                                           DCERPC_PFC_FLAG_FIRST |
1664                                           DCERPC_PFC_FLAG_LAST,
1665                                           pauth_blob->length,
1666                                           rpc_call_id,
1667                                           &u,
1668                                           rpc_out);
1669         data_blob_free(&u.auth3.auth_info);
1670         if (!NT_STATUS_IS_OK(status)) {
1671                 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1672                 return status;
1673         }
1674
1675         return NT_STATUS_OK;
1676 }
1677
1678 /*******************************************************************
1679  Creates a DCE/RPC bind alter context authentication request which
1680  may contain a spnego auth blobl
1681  ********************************************************************/
1682
1683 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1684                                         enum dcerpc_AuthType auth_type,
1685                                         enum dcerpc_AuthLevel auth_level,
1686                                         uint32 rpc_call_id,
1687                                         const struct ndr_syntax_id *abstract,
1688                                         const struct ndr_syntax_id *transfer,
1689                                         const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1690                                         DATA_BLOB *rpc_out)
1691 {
1692         DATA_BLOB auth_info;
1693         NTSTATUS status;
1694
1695         status = dcerpc_push_dcerpc_auth(mem_ctx,
1696                                          auth_type,
1697                                          auth_level,
1698                                          0, /* auth_pad_length */
1699                                          1, /* auth_context_id */
1700                                          pauth_blob,
1701                                          &auth_info);
1702         if (!NT_STATUS_IS_OK(status)) {
1703                 return status;
1704         }
1705
1706         status = create_bind_or_alt_ctx_internal(mem_ctx,
1707                                                  DCERPC_PKT_ALTER,
1708                                                  rpc_call_id,
1709                                                  abstract,
1710                                                  transfer,
1711                                                  &auth_info,
1712                                                  false, /* client_hdr_signing */
1713                                                  rpc_out);
1714         data_blob_free(&auth_info);
1715         return status;
1716 }
1717
1718 /****************************************************************************
1719  Do an rpc bind.
1720 ****************************************************************************/
1721
1722 struct rpc_pipe_bind_state {
1723         struct tevent_context *ev;
1724         struct rpc_pipe_client *cli;
1725         DATA_BLOB rpc_out;
1726         bool auth3;
1727         uint32_t rpc_call_id;
1728 };
1729
1730 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1731 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1732                                    struct rpc_pipe_bind_state *state,
1733                                    DATA_BLOB *credentials);
1734 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1735                                      struct rpc_pipe_bind_state *state,
1736                                      DATA_BLOB *credentials);
1737
1738 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1739                                       struct tevent_context *ev,
1740                                       struct rpc_pipe_client *cli,
1741                                       struct pipe_auth_data *auth)
1742 {
1743         struct tevent_req *req, *subreq;
1744         struct rpc_pipe_bind_state *state;
1745         NTSTATUS status;
1746
1747         req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1748         if (req == NULL) {
1749                 return NULL;
1750         }
1751
1752         DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1753                 rpccli_pipe_txt(talloc_tos(), cli),
1754                 (unsigned int)auth->auth_type,
1755                 (unsigned int)auth->auth_level ));
1756
1757         state->ev = ev;
1758         state->cli = cli;
1759         state->rpc_call_id = get_rpc_call_id();
1760
1761         cli->auth = talloc_move(cli, &auth);
1762
1763         /* Marshall the outgoing data. */
1764         status = create_rpc_bind_req(state, cli,
1765                                      cli->auth,
1766                                      state->rpc_call_id,
1767                                      &cli->abstract_syntax,
1768                                      &cli->transfer_syntax,
1769                                      &state->rpc_out);
1770
1771         if (!NT_STATUS_IS_OK(status) &&
1772             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1773                 goto post_status;
1774         }
1775
1776         subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1777                                    DCERPC_PKT_BIND_ACK, state->rpc_call_id);
1778         if (subreq == NULL) {
1779                 goto fail;
1780         }
1781         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1782         return req;
1783
1784  post_status:
1785         tevent_req_nterror(req, status);
1786         return tevent_req_post(req, ev);
1787  fail:
1788         TALLOC_FREE(req);
1789         return NULL;
1790 }
1791
1792 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1793 {
1794         struct tevent_req *req = tevent_req_callback_data(
1795                 subreq, struct tevent_req);
1796         struct rpc_pipe_bind_state *state = tevent_req_data(
1797                 req, struct rpc_pipe_bind_state);
1798         struct pipe_auth_data *pauth = state->cli->auth;
1799         struct gensec_security *gensec_security;
1800         struct ncacn_packet *pkt = NULL;
1801         struct dcerpc_auth auth;
1802         DATA_BLOB auth_token = data_blob_null;
1803         NTSTATUS status;
1804
1805         status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
1806         TALLOC_FREE(subreq);
1807         if (!NT_STATUS_IS_OK(status)) {
1808                 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1809                           rpccli_pipe_txt(talloc_tos(), state->cli),
1810                           nt_errstr(status)));
1811                 tevent_req_nterror(req, status);
1812                 return;
1813         }
1814
1815         if (state->auth3) {
1816                 tevent_req_done(req);
1817                 return;
1818         }
1819
1820         if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1821                 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1822                 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1823                 return;
1824         }
1825
1826         state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1827         state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1828
1829         switch(pauth->auth_type) {
1830
1831         case DCERPC_AUTH_TYPE_NONE:
1832         case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1833                 /* Bind complete. */
1834                 tevent_req_done(req);
1835                 return;
1836
1837         default:
1838                 /* Paranoid lenght checks */
1839                 if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH
1840                                                 + pkt->auth_length) {
1841                         tevent_req_nterror(req,
1842                                         NT_STATUS_INFO_LENGTH_MISMATCH);
1843                         return;
1844                 }
1845                 /* get auth credentials */
1846                 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
1847                                                  &pkt->u.bind_ack.auth_info,
1848                                                  &auth, false);
1849                 if (!NT_STATUS_IS_OK(status)) {
1850                         DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1851                                   nt_errstr(status)));
1852                         tevent_req_nterror(req, status);
1853                         return;
1854                 }
1855                 break;
1856         }
1857
1858         /*
1859          * For authenticated binds we may need to do 3 or 4 leg binds.
1860          */
1861
1862         switch(pauth->auth_type) {
1863
1864         case DCERPC_AUTH_TYPE_NONE:
1865         case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
1866                 /* Bind complete. */
1867                 tevent_req_done(req);
1868                 return;
1869
1870         default:
1871                 gensec_security = talloc_get_type_abort(pauth->auth_ctx,
1872                                                 struct gensec_security);
1873
1874                 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1875                         if (pauth->client_hdr_signing) {
1876                                 pauth->hdr_signing = true;
1877                                 gensec_want_feature(gensec_security,
1878                                                     GENSEC_FEATURE_SIGN_PKT_HEADER);
1879                         }
1880                 }
1881
1882                 status = gensec_update(gensec_security, state,
1883                                        auth.credentials, &auth_token);
1884                 if (NT_STATUS_EQUAL(status,
1885                                     NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1886                         status = rpc_bind_next_send(req, state,
1887                                                         &auth_token);
1888                 } else if (NT_STATUS_IS_OK(status)) {
1889                         if (auth_token.length == 0) {
1890                                 /* Bind complete. */
1891                                 tevent_req_done(req);
1892                                 return;
1893                         }
1894                         status = rpc_bind_finish_send(req, state,
1895                                                         &auth_token);
1896                 }
1897                 break;
1898         }
1899
1900         if (!NT_STATUS_IS_OK(status)) {
1901                 tevent_req_nterror(req, status);
1902         }
1903         return;
1904 }
1905
1906 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1907                                    struct rpc_pipe_bind_state *state,
1908                                    DATA_BLOB *auth_token)
1909 {
1910         struct pipe_auth_data *auth = state->cli->auth;
1911         struct tevent_req *subreq;
1912         NTSTATUS status;
1913
1914         /* Now prepare the alter context pdu. */
1915         data_blob_free(&state->rpc_out);
1916
1917         status = create_rpc_alter_context(state,
1918                                           auth->auth_type,
1919                                           auth->auth_level,
1920                                           state->rpc_call_id,
1921                                           &state->cli->abstract_syntax,
1922                                           &state->cli->transfer_syntax,
1923                                           auth_token,
1924                                           &state->rpc_out);
1925         if (!NT_STATUS_IS_OK(status)) {
1926                 return status;
1927         }
1928
1929         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1930                                    &state->rpc_out, DCERPC_PKT_ALTER_RESP,
1931                                    state->rpc_call_id);
1932         if (subreq == NULL) {
1933                 return NT_STATUS_NO_MEMORY;
1934         }
1935         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1936         return NT_STATUS_OK;
1937 }
1938
1939 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1940                                      struct rpc_pipe_bind_state *state,
1941                                      DATA_BLOB *auth_token)
1942 {
1943         struct pipe_auth_data *auth = state->cli->auth;
1944         struct tevent_req *subreq;
1945         NTSTATUS status;
1946
1947         state->auth3 = true;
1948
1949         /* Now prepare the auth3 context pdu. */
1950         data_blob_free(&state->rpc_out);
1951
1952         status = create_rpc_bind_auth3(state, state->cli,
1953                                         state->rpc_call_id,
1954                                         auth->auth_type,
1955                                         auth->auth_level,
1956                                         auth_token,
1957                                         &state->rpc_out);
1958         if (!NT_STATUS_IS_OK(status)) {
1959                 return status;
1960         }
1961
1962         subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1963                                    &state->rpc_out, DCERPC_PKT_AUTH3,
1964                                    state->rpc_call_id);
1965         if (subreq == NULL) {
1966                 return NT_STATUS_NO_MEMORY;
1967         }
1968         tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1969         return NT_STATUS_OK;
1970 }
1971
1972 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
1973 {
1974         return tevent_req_simple_recv_ntstatus(req);
1975 }
1976
1977 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
1978                        struct pipe_auth_data *auth)
1979 {
1980         TALLOC_CTX *frame = talloc_stackframe();
1981         struct tevent_context *ev;
1982         struct tevent_req *req;
1983         NTSTATUS status = NT_STATUS_OK;
1984
1985         ev = samba_tevent_context_init(frame);
1986         if (ev == NULL) {
1987                 status = NT_STATUS_NO_MEMORY;
1988                 goto fail;
1989         }
1990
1991         req = rpc_pipe_bind_send(frame, ev, cli, auth);
1992         if (req == NULL) {
1993                 status = NT_STATUS_NO_MEMORY;
1994                 goto fail;
1995         }
1996
1997         if (!tevent_req_poll(req, ev)) {
1998                 status = map_nt_error_from_unix(errno);
1999                 goto fail;
2000         }
2001
2002         status = rpc_pipe_bind_recv(req);
2003  fail:
2004         TALLOC_FREE(frame);
2005         return status;
2006 }
2007
2008 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2009
2010 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2011                                 unsigned int timeout)
2012 {
2013         unsigned int old;
2014
2015         if (rpc_cli->transport == NULL) {
2016                 return RPCCLI_DEFAULT_TIMEOUT;
2017         }
2018
2019         if (rpc_cli->transport->set_timeout == NULL) {
2020                 return RPCCLI_DEFAULT_TIMEOUT;
2021         }
2022
2023         old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2024         if (old == 0) {
2025                 return RPCCLI_DEFAULT_TIMEOUT;
2026         }
2027
2028         return old;
2029 }
2030
2031 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2032 {
2033         if (rpc_cli == NULL) {
2034                 return false;
2035         }
2036
2037         if (rpc_cli->transport == NULL) {
2038                 return false;
2039         }
2040
2041         return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2042 }
2043
2044 struct rpccli_bh_state {
2045         struct rpc_pipe_client *rpc_cli;
2046 };
2047
2048 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2049 {
2050         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2051                                      struct rpccli_bh_state);
2052
2053         return rpccli_is_connected(hs->rpc_cli);
2054 }
2055
2056 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2057                                       uint32_t timeout)
2058 {
2059         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2060                                      struct rpccli_bh_state);
2061
2062         return rpccli_set_timeout(hs->rpc_cli, timeout);
2063 }
2064
2065 static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
2066                                 enum dcerpc_AuthType *auth_type,
2067                                 enum dcerpc_AuthLevel *auth_level)
2068 {
2069         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2070                                      struct rpccli_bh_state);
2071
2072         if (hs->rpc_cli == NULL) {
2073                 return;
2074         }
2075
2076         if (hs->rpc_cli->auth == NULL) {
2077                 return;
2078         }
2079
2080         *auth_type = hs->rpc_cli->auth->auth_type;
2081         *auth_level = hs->rpc_cli->auth->auth_level;
2082 }
2083
2084 struct rpccli_bh_raw_call_state {
2085         DATA_BLOB in_data;
2086         DATA_BLOB out_data;
2087         uint32_t out_flags;
2088 };
2089
2090 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2091
2092 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2093                                                   struct tevent_context *ev,
2094                                                   struct dcerpc_binding_handle *h,
2095                                                   const struct GUID *object,
2096                                                   uint32_t opnum,
2097                                                   uint32_t in_flags,
2098                                                   const uint8_t *in_data,
2099                                                   size_t in_length)
2100 {
2101         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2102                                      struct rpccli_bh_state);
2103         struct tevent_req *req;
2104         struct rpccli_bh_raw_call_state *state;
2105         bool ok;
2106         struct tevent_req *subreq;
2107
2108         req = tevent_req_create(mem_ctx, &state,
2109                                 struct rpccli_bh_raw_call_state);
2110         if (req == NULL) {
2111                 return NULL;
2112         }
2113         state->in_data.data = discard_const_p(uint8_t, in_data);
2114         state->in_data.length = in_length;
2115
2116         ok = rpccli_bh_is_connected(h);
2117         if (!ok) {
2118                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2119                 return tevent_req_post(req, ev);
2120         }
2121
2122         subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2123                                        opnum, &state->in_data);
2124         if (tevent_req_nomem(subreq, req)) {
2125                 return tevent_req_post(req, ev);
2126         }
2127         tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2128
2129         return req;
2130 }
2131
2132 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2133 {
2134         struct tevent_req *req =
2135                 tevent_req_callback_data(subreq,
2136                 struct tevent_req);
2137         struct rpccli_bh_raw_call_state *state =
2138                 tevent_req_data(req,
2139                 struct rpccli_bh_raw_call_state);
2140         NTSTATUS status;
2141
2142         state->out_flags = 0;
2143
2144         /* TODO: support bigendian responses */
2145
2146         status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2147         TALLOC_FREE(subreq);
2148         if (!NT_STATUS_IS_OK(status)) {
2149                 tevent_req_nterror(req, status);
2150                 return;
2151         }
2152
2153         tevent_req_done(req);
2154 }
2155
2156 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2157                                         TALLOC_CTX *mem_ctx,
2158                                         uint8_t **out_data,
2159                                         size_t *out_length,
2160                                         uint32_t *out_flags)
2161 {
2162         struct rpccli_bh_raw_call_state *state =
2163                 tevent_req_data(req,
2164                 struct rpccli_bh_raw_call_state);
2165         NTSTATUS status;
2166
2167         if (tevent_req_is_nterror(req, &status)) {
2168                 tevent_req_received(req);
2169                 return status;
2170         }
2171
2172         *out_data = talloc_move(mem_ctx, &state->out_data.data);
2173         *out_length = state->out_data.length;
2174         *out_flags = state->out_flags;
2175         tevent_req_received(req);
2176         return NT_STATUS_OK;
2177 }
2178
2179 struct rpccli_bh_disconnect_state {
2180         uint8_t _dummy;
2181 };
2182
2183 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2184                                                 struct tevent_context *ev,
2185                                                 struct dcerpc_binding_handle *h)
2186 {
2187         struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2188                                      struct rpccli_bh_state);
2189         struct tevent_req *req;
2190         struct rpccli_bh_disconnect_state *state;
2191         bool ok;
2192
2193         req = tevent_req_create(mem_ctx, &state,
2194                                 struct rpccli_bh_disconnect_state);
2195         if (req == NULL) {
2196                 return NULL;
2197         }
2198
2199         ok = rpccli_bh_is_connected(h);
2200         if (!ok) {
2201                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2202                 return tevent_req_post(req, ev);
2203         }
2204
2205         /*
2206          * TODO: do a real async disconnect ...
2207          *
2208          * For now the caller needs to free rpc_cli
2209          */
2210         hs->rpc_cli = NULL;
2211
2212         tevent_req_done(req);
2213         return tevent_req_post(req, ev);
2214 }
2215
2216 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2217 {
2218         NTSTATUS status;
2219
2220         if (tevent_req_is_nterror(req, &status)) {
2221                 tevent_req_received(req);
2222                 return status;
2223         }
2224
2225         tevent_req_received(req);
2226         return NT_STATUS_OK;
2227 }
2228
2229 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2230 {
2231         return true;
2232 }
2233
2234 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2235                                    int ndr_flags,
2236                                    const void *_struct_ptr,
2237                                    const struct ndr_interface_call *call)
2238 {
2239         void *struct_ptr = discard_const(_struct_ptr);
2240
2241         if (DEBUGLEVEL < 10) {
2242                 return;
2243         }
2244
2245         if (ndr_flags & NDR_IN) {
2246                 ndr_print_function_debug(call->ndr_print,
2247                                          call->name,
2248                                          ndr_flags,
2249                                          struct_ptr);
2250         }
2251         if (ndr_flags & NDR_OUT) {
2252                 ndr_print_function_debug(call->ndr_print,
2253                                          call->name,
2254                                          ndr_flags,
2255                                          struct_ptr);
2256         }
2257 }
2258
2259 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2260         .name                   = "rpccli",
2261         .is_connected           = rpccli_bh_is_connected,
2262         .set_timeout            = rpccli_bh_set_timeout,
2263         .auth_info              = rpccli_bh_auth_info,
2264         .raw_call_send          = rpccli_bh_raw_call_send,
2265         .raw_call_recv          = rpccli_bh_raw_call_recv,
2266         .disconnect_send        = rpccli_bh_disconnect_send,
2267         .disconnect_recv        = rpccli_bh_disconnect_recv,
2268
2269         .ref_alloc              = rpccli_bh_ref_alloc,
2270         .do_ndr_print           = rpccli_bh_do_ndr_print,
2271 };
2272
2273 /* initialise a rpc_pipe_client binding handle */
2274 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2275                                         const struct GUID *object,
2276                                         const struct ndr_interface_table *table)
2277 {
2278         struct dcerpc_binding_handle *h;
2279         struct rpccli_bh_state *hs;
2280
2281         h = dcerpc_binding_handle_create(c,
2282                                          &rpccli_bh_ops,
2283                                          object,
2284                                          table,
2285                                          &hs,
2286                                          struct rpccli_bh_state,
2287                                          __location__);
2288         if (h == NULL) {
2289                 return NULL;
2290         }
2291         hs->rpc_cli = c;
2292
2293         return h;
2294 }
2295
2296 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2297                                   struct pipe_auth_data **presult)
2298 {
2299         struct pipe_auth_data *result;
2300
2301         result = talloc_zero(mem_ctx, struct pipe_auth_data);
2302         if (result == NULL) {
2303                 return NT_STATUS_NO_MEMORY;
2304         }
2305
2306         result->auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM;
2307         result->auth_level = DCERPC_AUTH_LEVEL_CONNECT;
2308
2309         result->user_name = talloc_strdup(result, "");
2310         result->domain = talloc_strdup(result, "");
2311         if ((result->user_name == NULL) || (result->domain == NULL)) {
2312                 TALLOC_FREE(result);
2313                 return NT_STATUS_NO_MEMORY;
2314         }
2315
2316         *presult = result;
2317         return NT_STATUS_OK;
2318 }
2319
2320 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2321                                struct pipe_auth_data **presult)
2322 {
2323         struct pipe_auth_data *result;
2324
2325         result = talloc_zero(mem_ctx, struct pipe_auth_data);
2326         if (result == NULL) {
2327                 return NT_STATUS_NO_MEMORY;
2328         }
2329
2330         result->auth_type = DCERPC_AUTH_TYPE_NONE;
2331         result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2332
2333         result->user_name = talloc_strdup(result, "");
2334         result->domain = talloc_strdup(result, "");
2335         if ((result->user_name == NULL) || (result->domain == NULL)) {
2336                 TALLOC_FREE(result);
2337                 return NT_STATUS_NO_MEMORY;
2338         }
2339
2340         *presult = result;
2341         return NT_STATUS_OK;
2342 }
2343
2344 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2345                                          enum dcerpc_AuthType auth_type,
2346                                          enum dcerpc_AuthLevel auth_level,
2347                                          const char *server,
2348                                          const char *target_service,
2349                                          const char *domain,
2350                                          const char *username,
2351                                          const char *password,
2352                                          enum credentials_use_kerberos use_kerberos,
2353                                          struct netlogon_creds_CredentialState *creds,
2354                                          struct pipe_auth_data **presult)
2355 {
2356         struct auth_generic_state *auth_generic_ctx;
2357         struct pipe_auth_data *result;
2358         NTSTATUS status;
2359
2360         result = talloc_zero(mem_ctx, struct pipe_auth_data);
2361         if (result == NULL) {
2362                 return NT_STATUS_NO_MEMORY;
2363         }
2364
2365         result->auth_type = auth_type;
2366         result->auth_level = auth_level;
2367
2368         result->user_name = talloc_strdup(result, username);
2369         result->domain = talloc_strdup(result, domain);
2370         if ((result->user_name == NULL) || (result->domain == NULL)) {
2371                 status = NT_STATUS_NO_MEMORY;
2372                 goto fail;
2373         }
2374
2375         status = auth_generic_client_prepare(result,
2376                                              &auth_generic_ctx);
2377         if (!NT_STATUS_IS_OK(status)) {
2378                 goto fail;
2379         }
2380
2381         status = auth_generic_set_username(auth_generic_ctx, username);
2382         if (!NT_STATUS_IS_OK(status)) {
2383                 goto fail;
2384         }
2385
2386         status = auth_generic_set_domain(auth_generic_ctx, domain);
2387         if (!NT_STATUS_IS_OK(status)) {
2388                 goto fail;
2389         }
2390
2391         status = auth_generic_set_password(auth_generic_ctx, password);
2392         if (!NT_STATUS_IS_OK(status)) {
2393                 goto fail;
2394         }
2395
2396         status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2397         if (!NT_STATUS_IS_OK(status)) {
2398                 goto fail;
2399         }
2400
2401         status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2402         if (!NT_STATUS_IS_OK(status)) {
2403                 goto fail;
2404         }
2405
2406         cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos);
2407         cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
2408
2409         status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2410         if (!NT_STATUS_IS_OK(status)) {
2411                 goto fail;
2412         }
2413
2414         result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2415         talloc_free(auth_generic_ctx);
2416         *presult = result;
2417         return NT_STATUS_OK;
2418
2419  fail:
2420         TALLOC_FREE(result);
2421         return status;
2422 }
2423
2424 /**
2425  * Create an rpc pipe client struct, connecting to a tcp port.
2426  */
2427 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2428                                        const struct sockaddr_storage *ss_addr,
2429                                        uint16_t port,
2430                                        const struct ndr_interface_table *table,
2431                                        struct rpc_pipe_client **presult)
2432 {
2433         struct rpc_pipe_client *result;
2434         struct sockaddr_storage addr;
2435         NTSTATUS status;
2436         int fd;
2437
2438         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2439         if (result == NULL) {
2440                 return NT_STATUS_NO_MEMORY;
2441         }
2442
2443         result->abstract_syntax = table->syntax_id;
2444         result->transfer_syntax = ndr_transfer_syntax_ndr;
2445
2446         result->desthost = talloc_strdup(result, host);
2447         result->srv_name_slash = talloc_asprintf_strupper_m(
2448                 result, "\\\\%s", result->desthost);
2449         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2450                 status = NT_STATUS_NO_MEMORY;
2451                 goto fail;
2452         }
2453
2454         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2455         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2456
2457         if (ss_addr == NULL) {
2458                 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2459                         status = NT_STATUS_NOT_FOUND;
2460                         goto fail;
2461                 }
2462         } else {
2463                 addr = *ss_addr;
2464         }
2465
2466         status = open_socket_out(&addr, port, 60*1000, &fd);
2467         if (!NT_STATUS_IS_OK(status)) {
2468                 goto fail;
2469         }
2470         set_socket_options(fd, lp_socket_options());
2471
2472         status = rpc_transport_sock_init(result, fd, &result->transport);
2473         if (!NT_STATUS_IS_OK(status)) {
2474                 close(fd);
2475                 goto fail;
2476         }
2477
2478         result->transport->transport = NCACN_IP_TCP;
2479
2480         result->binding_handle = rpccli_bh_create(result, NULL, table);
2481         if (result->binding_handle == NULL) {
2482                 TALLOC_FREE(result);
2483                 return NT_STATUS_NO_MEMORY;
2484         }
2485
2486         *presult = result;
2487         return NT_STATUS_OK;
2488
2489  fail:
2490         TALLOC_FREE(result);
2491         return status;
2492 }
2493
2494 /**
2495  * Determine the tcp port on which a dcerpc interface is listening
2496  * for the ncacn_ip_tcp transport via the endpoint mapper of the
2497  * target host.
2498  */
2499 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2500                                       const struct sockaddr_storage *addr,
2501                                       const struct ndr_interface_table *table,
2502                                       uint16_t *pport)
2503 {
2504         NTSTATUS status;
2505         struct rpc_pipe_client *epm_pipe = NULL;
2506         struct dcerpc_binding_handle *epm_handle = NULL;
2507         struct pipe_auth_data *auth = NULL;
2508         struct dcerpc_binding *map_binding = NULL;
2509         struct dcerpc_binding *res_binding = NULL;
2510         enum dcerpc_transport_t transport;
2511         const char *endpoint = NULL;
2512         struct epm_twr_t *map_tower = NULL;
2513         struct epm_twr_t *res_towers = NULL;
2514         struct policy_handle *entry_handle = NULL;
2515         uint32_t num_towers = 0;
2516         uint32_t max_towers = 1;
2517         struct epm_twr_p_t towers;
2518         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2519         uint32_t result = 0;
2520
2521         if (pport == NULL) {
2522                 status = NT_STATUS_INVALID_PARAMETER;
2523                 goto done;
2524         }
2525
2526         if (ndr_syntax_id_equal(&table->syntax_id,
2527                                 &ndr_table_epmapper.syntax_id)) {
2528                 *pport = 135;
2529                 status = NT_STATUS_OK;
2530                 goto done;
2531         }
2532
2533         /* open the connection to the endpoint mapper */
2534         status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2535                                         &ndr_table_epmapper,
2536                                         &epm_pipe);
2537
2538         if (!NT_STATUS_IS_OK(status)) {
2539                 goto done;
2540         }
2541         epm_handle = epm_pipe->binding_handle;
2542
2543         status = rpccli_anon_bind_data(tmp_ctx, &auth);
2544         if (!NT_STATUS_IS_OK(status)) {
2545                 goto done;
2546         }
2547
2548         status = rpc_pipe_bind(epm_pipe, auth);
2549         if (!NT_STATUS_IS_OK(status)) {
2550                 goto done;
2551         }
2552
2553         /* create tower for asking the epmapper */
2554
2555         status = dcerpc_parse_binding(tmp_ctx, "ncacn_ip_tcp:[135]",
2556                                       &map_binding);
2557         if (!NT_STATUS_IS_OK(status)) {
2558                 goto done;
2559         }
2560
2561         status = dcerpc_binding_set_abstract_syntax(map_binding,
2562                                                     &table->syntax_id);
2563         if (!NT_STATUS_IS_OK(status)) {
2564                 goto done;
2565         }
2566
2567         map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
2568         if (map_tower == NULL) {
2569                 status = NT_STATUS_NO_MEMORY;
2570                 goto done;
2571         }
2572
2573         status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2574                                             &(map_tower->tower));
2575         if (!NT_STATUS_IS_OK(status)) {
2576                 goto done;
2577         }
2578
2579         /* allocate further parameters for the epm_Map call */
2580
2581         res_towers = talloc_array(tmp_ctx, struct epm_twr_t, max_towers);
2582         if (res_towers == NULL) {
2583                 status = NT_STATUS_NO_MEMORY;
2584                 goto done;
2585         }
2586         towers.twr = res_towers;
2587
2588         entry_handle = talloc_zero(tmp_ctx, struct policy_handle);
2589         if (entry_handle == NULL) {
2590                 status = NT_STATUS_NO_MEMORY;
2591                 goto done;
2592         }
2593
2594         /* ask the endpoint mapper for the port */
2595
2596         status = dcerpc_epm_Map(epm_handle,
2597                                 tmp_ctx,
2598                                 discard_const_p(struct GUID,
2599                                               &(table->syntax_id.uuid)),
2600                                 map_tower,
2601                                 entry_handle,
2602                                 max_towers,
2603                                 &num_towers,
2604                                 &towers,
2605                                 &result);
2606
2607         if (!NT_STATUS_IS_OK(status)) {
2608                 goto done;
2609         }
2610
2611         if (result != EPMAPPER_STATUS_OK) {
2612                 status = NT_STATUS_UNSUCCESSFUL;
2613                 goto done;
2614         }
2615
2616         if (num_towers != 1) {
2617                 status = NT_STATUS_UNSUCCESSFUL;
2618                 goto done;
2619         }
2620
2621         /* extract the port from the answer */
2622
2623         status = dcerpc_binding_from_tower(tmp_ctx,
2624                                            &(towers.twr->tower),
2625                                            &res_binding);
2626         if (!NT_STATUS_IS_OK(status)) {
2627                 goto done;
2628         }
2629
2630         transport = dcerpc_binding_get_transport(res_binding);
2631         endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
2632
2633         /* are further checks here necessary? */
2634         if (transport != NCACN_IP_TCP) {
2635                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2636                 goto done;
2637         }
2638
2639         if (endpoint == NULL) {
2640                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2641                 goto done;
2642         }
2643
2644         *pport = (uint16_t)atoi(endpoint);
2645
2646 done:
2647         TALLOC_FREE(tmp_ctx);
2648         return status;
2649 }
2650
2651 /**
2652  * Create a rpc pipe client struct, connecting to a host via tcp.
2653  * The port is determined by asking the endpoint mapper on the given
2654  * host.
2655  */
2656 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2657                            const struct sockaddr_storage *addr,
2658                            const struct ndr_interface_table *table,
2659                            struct rpc_pipe_client **presult)
2660 {
2661         NTSTATUS status;
2662         uint16_t port = 0;
2663
2664         status = rpc_pipe_get_tcp_port(host, addr, table, &port);
2665         if (!NT_STATUS_IS_OK(status)) {
2666                 return status;
2667         }
2668
2669         return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2670                                       table, presult);
2671 }
2672
2673 /********************************************************************
2674  Create a rpc pipe client struct, connecting to a unix domain socket
2675  ********************************************************************/
2676 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2677                                const struct ndr_interface_table *table,
2678                                struct rpc_pipe_client **presult)
2679 {
2680         struct rpc_pipe_client *result;
2681         struct sockaddr_un addr;
2682         NTSTATUS status;
2683         int fd;
2684         socklen_t salen;
2685
2686         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2687         if (result == NULL) {
2688                 return NT_STATUS_NO_MEMORY;
2689         }
2690
2691         result->abstract_syntax = table->syntax_id;
2692         result->transfer_syntax = ndr_transfer_syntax_ndr;
2693
2694         result->desthost = get_myname(result);
2695         result->srv_name_slash = talloc_asprintf_strupper_m(
2696                 result, "\\\\%s", result->desthost);
2697         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2698                 status = NT_STATUS_NO_MEMORY;
2699                 goto fail;
2700         }
2701
2702         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2703         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2704
2705         fd = socket(AF_UNIX, SOCK_STREAM, 0);
2706         if (fd == -1) {
2707                 status = map_nt_error_from_unix(errno);
2708                 goto fail;
2709         }
2710
2711         ZERO_STRUCT(addr);
2712         addr.sun_family = AF_UNIX;
2713         strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2714         salen = sizeof(struct sockaddr_un);
2715
2716         if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
2717                 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2718                           strerror(errno)));
2719                 close(fd);
2720                 return map_nt_error_from_unix(errno);
2721         }
2722
2723         status = rpc_transport_sock_init(result, fd, &result->transport);
2724         if (!NT_STATUS_IS_OK(status)) {
2725                 close(fd);
2726                 goto fail;
2727         }
2728
2729         result->transport->transport = NCALRPC;
2730
2731         result->binding_handle = rpccli_bh_create(result, NULL, table);
2732         if (result->binding_handle == NULL) {
2733                 TALLOC_FREE(result);
2734                 return NT_STATUS_NO_MEMORY;
2735         }
2736
2737         *presult = result;
2738         return NT_STATUS_OK;
2739
2740  fail:
2741         TALLOC_FREE(result);
2742         return status;
2743 }
2744
2745 struct rpc_pipe_client_np_ref {
2746         struct cli_state *cli;
2747         struct rpc_pipe_client *pipe;
2748 };
2749
2750 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2751 {
2752         DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2753         return 0;
2754 }
2755
2756 /****************************************************************************
2757  Open a named pipe over SMB to a remote server.
2758  *
2759  * CAVEAT CALLER OF THIS FUNCTION:
2760  *    The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2761  *    so be sure that this function is called AFTER any structure (vs pointer)
2762  *    assignment of the cli.  In particular, libsmbclient does structure
2763  *    assignments of cli, which invalidates the data in the returned
2764  *    rpc_pipe_client if this function is called before the structure assignment
2765  *    of cli.
2766  * 
2767  ****************************************************************************/
2768
2769 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2770                                  const struct ndr_interface_table *table,
2771                                  struct rpc_pipe_client **presult)
2772 {
2773         struct rpc_pipe_client *result;
2774         NTSTATUS status;
2775         struct rpc_pipe_client_np_ref *np_ref;
2776
2777         /* sanity check to protect against crashes */
2778
2779         if ( !cli ) {
2780                 return NT_STATUS_INVALID_HANDLE;
2781         }
2782
2783         result = talloc_zero(NULL, struct rpc_pipe_client);
2784         if (result == NULL) {
2785                 return NT_STATUS_NO_MEMORY;
2786         }
2787
2788         result->abstract_syntax = table->syntax_id;
2789         result->transfer_syntax = ndr_transfer_syntax_ndr;
2790         result->desthost = talloc_strdup(result, smbXcli_conn_remote_name(cli->conn));
2791         result->srv_name_slash = talloc_asprintf_strupper_m(
2792                 result, "\\\\%s", result->desthost);
2793
2794         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2795         result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2796
2797         if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2798                 TALLOC_FREE(result);
2799                 return NT_STATUS_NO_MEMORY;
2800         }
2801
2802         status = rpc_transport_np_init(result, cli, table,
2803                                        &result->transport);
2804         if (!NT_STATUS_IS_OK(status)) {
2805                 TALLOC_FREE(result);
2806                 return status;
2807         }
2808
2809         result->transport->transport = NCACN_NP;
2810
2811         np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
2812         if (np_ref == NULL) {
2813                 TALLOC_FREE(result);
2814                 return NT_STATUS_NO_MEMORY;
2815         }
2816         np_ref->cli = cli;
2817         np_ref->pipe = result;
2818
2819         DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
2820         talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
2821
2822         result->binding_handle = rpccli_bh_create(result, NULL, table);
2823         if (result->binding_handle == NULL) {
2824                 TALLOC_FREE(result);
2825                 return NT_STATUS_NO_MEMORY;
2826         }
2827
2828         *presult = result;
2829         return NT_STATUS_OK;
2830 }
2831
2832 /****************************************************************************
2833  Open a pipe to a remote server.
2834  ****************************************************************************/
2835
2836 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2837                                   enum dcerpc_transport_t transport,
2838                                   const struct ndr_interface_table *table,
2839                                   struct rpc_pipe_client **presult)
2840 {
2841         switch (transport) {
2842         case NCACN_IP_TCP:
2843                 return rpc_pipe_open_tcp(NULL,
2844                                          smbXcli_conn_remote_name(cli->conn),
2845                                          smbXcli_conn_remote_sockaddr(cli->conn),
2846                                          table, presult);
2847         case NCACN_NP:
2848                 return rpc_pipe_open_np(cli, table, presult);
2849         default:
2850                 return NT_STATUS_NOT_IMPLEMENTED;
2851         }
2852 }
2853
2854 /****************************************************************************
2855  Open a named pipe to an SMB server and bind anonymously.
2856  ****************************************************************************/
2857
2858 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
2859                                             enum dcerpc_transport_t transport,
2860                                             const struct ndr_interface_table *table,
2861                                             struct rpc_pipe_client **presult)
2862 {
2863         struct rpc_pipe_client *result;
2864         struct pipe_auth_data *auth;
2865         NTSTATUS status;
2866
2867         status = cli_rpc_pipe_open(cli, transport, table, &result);
2868         if (!NT_STATUS_IS_OK(status)) {
2869                 return status;
2870         }
2871
2872         status = rpccli_anon_bind_data(result, &auth);
2873         if (!NT_STATUS_IS_OK(status)) {
2874                 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
2875                           nt_errstr(status)));
2876                 TALLOC_FREE(result);
2877                 return status;
2878         }
2879
2880         /*
2881          * This is a bit of an abstraction violation due to the fact that an
2882          * anonymous bind on an authenticated SMB inherits the user/domain
2883          * from the enclosing SMB creds
2884          */
2885
2886         TALLOC_FREE(auth->user_name);
2887         TALLOC_FREE(auth->domain);
2888
2889         auth->user_name = talloc_strdup(auth, cli->user_name);
2890         auth->domain = talloc_strdup(auth, cli->domain);
2891
2892         if (transport == NCACN_NP) {
2893                 struct smbXcli_session *session;
2894
2895                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2896                         session = cli->smb2.session;
2897                 } else {
2898                         session = cli->smb1.session;
2899                 }
2900
2901                 status = smbXcli_session_application_key(session, auth,
2902                                                 &auth->transport_session_key);
2903                 if (!NT_STATUS_IS_OK(status)) {
2904                         auth->transport_session_key = data_blob_null;
2905                 }
2906         }
2907
2908         if ((auth->user_name == NULL) || (auth->domain == NULL)) {
2909                 TALLOC_FREE(result);
2910                 return NT_STATUS_NO_MEMORY;
2911         }
2912
2913         status = rpc_pipe_bind(result, auth);
2914         if (!NT_STATUS_IS_OK(status)) {
2915                 int lvl = 0;
2916                 if (ndr_syntax_id_equal(&table->syntax_id,
2917                                         &ndr_table_dssetup.syntax_id)) {
2918                         /* non AD domains just don't have this pipe, avoid
2919                          * level 0 statement in that case - gd */
2920                         lvl = 3;
2921                 }
2922                 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
2923                             "%s failed with error %s\n",
2924                             table->name,
2925                             nt_errstr(status) ));
2926                 TALLOC_FREE(result);
2927                 return status;
2928         }
2929
2930         DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
2931                   "%s and bound anonymously.\n",
2932                   table->name,
2933                   result->desthost));
2934
2935         *presult = result;
2936         return NT_STATUS_OK;
2937 }
2938
2939 /****************************************************************************
2940  ****************************************************************************/
2941
2942 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
2943                                   const struct ndr_interface_table *table,
2944                                   struct rpc_pipe_client **presult)
2945 {
2946         return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
2947                                                   table, presult);
2948 }
2949
2950 /****************************************************************************
2951  Open a named pipe to an SMB server and bind using the mech specified
2952  ****************************************************************************/
2953
2954 NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
2955                                         const struct ndr_interface_table *table,
2956                                         enum dcerpc_transport_t transport,
2957                                         enum dcerpc_AuthType auth_type,
2958                                         enum dcerpc_AuthLevel auth_level,
2959                                         const char *server,
2960                                         const char *domain,
2961                                         const char *username,
2962                                         const char *password,
2963                                         struct rpc_pipe_client **presult)
2964 {
2965         struct rpc_pipe_client *result;
2966         struct pipe_auth_data *auth = NULL;
2967         const char *target_service = table->authservices->names[0];
2968         
2969         NTSTATUS status;
2970
2971         status = cli_rpc_pipe_open(cli, transport, table, &result);
2972         if (!NT_STATUS_IS_OK(status)) {
2973                 return status;
2974         }
2975
2976         status = rpccli_generic_bind_data(result,
2977                                           auth_type, auth_level,
2978                                           server, target_service,
2979                                           domain, username, password, 
2980                                           CRED_AUTO_USE_KERBEROS,
2981                                           NULL,
2982                                           &auth);
2983         if (!NT_STATUS_IS_OK(status)) {
2984                 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
2985                           nt_errstr(status)));
2986                 goto err;
2987         }
2988
2989         status = rpc_pipe_bind(result, auth);
2990         if (!NT_STATUS_IS_OK(status)) {
2991                 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
2992                         nt_errstr(status) ));
2993                 goto err;
2994         }
2995
2996         DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
2997                 "machine %s and bound as user %s\\%s.\n", table->name,
2998                   result->desthost, domain, username));
2999
3000         *presult = result;
3001         return NT_STATUS_OK;
3002
3003   err:
3004
3005         TALLOC_FREE(result);
3006         return status;
3007 }
3008
3009 /****************************************************************************
3010  External interface.
3011  Open a named pipe to an SMB server and bind using schannel (bind type 68)
3012  using session_key. sign and seal.
3013
3014  The *pdc will be stolen onto this new pipe
3015  ****************************************************************************/
3016
3017 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3018                                              const struct ndr_interface_table *table,
3019                                              enum dcerpc_transport_t transport,
3020                                              const char *domain,
3021                                              struct netlogon_creds_cli_context *netlogon_creds,
3022                                              struct rpc_pipe_client **_rpccli)
3023 {
3024         struct rpc_pipe_client *rpccli;
3025         struct pipe_auth_data *rpcauth;
3026         struct netlogon_creds_CredentialState *creds = NULL;
3027         enum dcerpc_AuthLevel auth_level;
3028         NTSTATUS status;
3029         const char *target_service = table->authservices->names[0];
3030         int rpc_pipe_bind_dbglvl = 0;
3031
3032         status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
3033         if (!NT_STATUS_IS_OK(status)) {
3034                 return status;
3035         }
3036
3037         status = netlogon_creds_cli_lock(netlogon_creds, rpccli, &creds);
3038         if (!NT_STATUS_IS_OK(status)) {
3039                 DEBUG(0, ("netlogon_creds_cli_get returned %s\n",
3040                           nt_errstr(status)));
3041                 TALLOC_FREE(rpccli);
3042                 return status;
3043         }
3044
3045         auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
3046
3047         status = rpccli_generic_bind_data(rpccli,
3048                                           DCERPC_AUTH_TYPE_SCHANNEL,
3049                                           auth_level,
3050                                           NULL,
3051                                           target_service,
3052                                           domain,
3053                                           creds->computer_name,
3054                                           NULL,
3055                                           CRED_AUTO_USE_KERBEROS,
3056                                           creds,
3057                                           &rpcauth);
3058         if (!NT_STATUS_IS_OK(status)) {
3059                 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3060                           nt_errstr(status)));
3061                 TALLOC_FREE(rpccli);
3062                 return status;
3063         }
3064
3065         status = rpc_pipe_bind(rpccli, rpcauth);
3066         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3067                 rpc_pipe_bind_dbglvl = 1;
3068                 netlogon_creds_cli_delete(netlogon_creds, &creds);
3069         }
3070         if (!NT_STATUS_IS_OK(status)) {
3071                 DEBUG(rpc_pipe_bind_dbglvl,
3072                       ("cli_rpc_pipe_open_schannel_with_key: "
3073                        "rpc_pipe_bind failed with error %s\n",
3074                        nt_errstr(status)));
3075                 TALLOC_FREE(rpccli);
3076                 return status;
3077         }
3078
3079         TALLOC_FREE(creds);
3080
3081         if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) {
3082                 goto done;
3083         }
3084
3085         status = netlogon_creds_cli_check(netlogon_creds,
3086                                           rpccli->binding_handle);
3087         if (!NT_STATUS_IS_OK(status)) {
3088                 DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
3089                           nt_errstr(status)));
3090                 TALLOC_FREE(rpccli);
3091                 return status;
3092         }
3093
3094
3095 done:
3096         DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3097                   "for domain %s and bound using schannel.\n",
3098                   table->name,
3099                   rpccli->desthost, domain));
3100
3101         *_rpccli = rpccli;
3102         return NT_STATUS_OK;
3103 }
3104
3105 NTSTATUS cli_rpc_pipe_open_spnego(struct cli_state *cli,
3106                                   const struct ndr_interface_table *table,
3107                                   enum dcerpc_transport_t transport,
3108                                   const char *oid,
3109                                   enum dcerpc_AuthLevel auth_level,
3110                                   const char *server,
3111                                   const char *domain,
3112                                   const char *username,
3113                                   const char *password,
3114                                   struct rpc_pipe_client **presult)
3115 {
3116         struct rpc_pipe_client *result;
3117         struct pipe_auth_data *auth = NULL;
3118         const char *target_service = table->authservices->names[0];
3119         
3120         NTSTATUS status;
3121         enum credentials_use_kerberos use_kerberos;
3122
3123         if (strcmp(oid, GENSEC_OID_KERBEROS5) == 0) {
3124                 use_kerberos = CRED_MUST_USE_KERBEROS;
3125         } else if (strcmp(oid, GENSEC_OID_NTLMSSP) == 0) {
3126                 use_kerberos = CRED_DONT_USE_KERBEROS;
3127         } else {
3128                 return NT_STATUS_INVALID_PARAMETER;
3129         }
3130
3131         status = cli_rpc_pipe_open(cli, transport, table, &result);
3132         if (!NT_STATUS_IS_OK(status)) {
3133                 return status;
3134         }
3135
3136         status = rpccli_generic_bind_data(result,
3137                                           DCERPC_AUTH_TYPE_SPNEGO, auth_level,
3138                                           server, target_service,
3139                                           domain, username, password, 
3140                                           use_kerberos, NULL,
3141                                           &auth);
3142         if (!NT_STATUS_IS_OK(status)) {
3143                 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3144                           nt_errstr(status)));
3145                 goto err;
3146         }
3147
3148         status = rpc_pipe_bind(result, auth);
3149         if (!NT_STATUS_IS_OK(status)) {
3150                 DEBUG(0, ("cli_rpc_pipe_open_spnego: cli_rpc_pipe_bind failed with error %s\n",
3151                         nt_errstr(status) ));
3152                 goto err;
3153         }
3154
3155         DEBUG(10,("cli_rpc_pipe_open_spnego: opened pipe %s to "
3156                   "machine %s.\n", table->name,
3157                   result->desthost));
3158
3159         *presult = result;
3160         return NT_STATUS_OK;
3161
3162   err:
3163
3164         TALLOC_FREE(result);
3165         return status;
3166 }
3167
3168 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3169                              struct rpc_pipe_client *cli,
3170                              DATA_BLOB *session_key)
3171 {
3172         NTSTATUS status;
3173         struct pipe_auth_data *a;
3174         struct gensec_security *gensec_security;
3175         DATA_BLOB sk = data_blob_null;
3176         bool make_dup = false;
3177
3178         if (!session_key || !cli) {
3179                 return NT_STATUS_INVALID_PARAMETER;
3180         }
3181
3182         a = cli->auth;
3183
3184         if (a == NULL) {
3185                 return NT_STATUS_INVALID_PARAMETER;
3186         }
3187
3188         switch (cli->auth->auth_type) {
3189         case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
3190         case DCERPC_AUTH_TYPE_NONE:
3191                 sk = data_blob_const(a->transport_session_key.data,
3192                                      a->transport_session_key.length);
3193                 make_dup = true;
3194                 break;
3195         default:
3196                 gensec_security = talloc_get_type(a->auth_ctx,
3197                                                   struct gensec_security);
3198                 status = gensec_session_key(gensec_security, mem_ctx, &sk);
3199                 if (!NT_STATUS_IS_OK(status)) {
3200                         return status;
3201                 }
3202                 make_dup = false;
3203                 break;
3204         }
3205
3206         if (!sk.data) {
3207                 return NT_STATUS_NO_USER_SESSION_KEY;
3208         }
3209
3210         if (make_dup) {
3211                 *session_key = data_blob_dup_talloc(mem_ctx, sk);
3212         } else {
3213                 *session_key = sk;
3214         }
3215
3216         return NT_STATUS_OK;
3217 }