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