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