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