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