f67869ffd503f0884dc165d01d90f9eec4fbf052
[bbaumbach/samba-autobuild/.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;
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;
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         if (result->desthost == NULL) {
2669                 status = NT_STATUS_NO_MEMORY;
2670                 goto fail;
2671         }
2672
2673         result->srv_name_slash = talloc_asprintf_strupper_m(
2674                 result, "\\\\%s", result->desthost);
2675         if (result->srv_name_slash == NULL) {
2676                 status = NT_STATUS_NO_MEMORY;
2677                 goto fail;
2678         }
2679
2680         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2681
2682         if (ss_addr == NULL) {
2683                 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2684                         status = NT_STATUS_NOT_FOUND;
2685                         goto fail;
2686                 }
2687         } else {
2688                 addr = *ss_addr;
2689         }
2690
2691         status = open_socket_out(&addr, port, 60*1000, &fd);
2692         if (!NT_STATUS_IS_OK(status)) {
2693                 goto fail;
2694         }
2695         set_socket_options(fd, lp_socket_options());
2696
2697         status = rpc_transport_sock_init(result, fd, &result->transport);
2698         if (!NT_STATUS_IS_OK(status)) {
2699                 close(fd);
2700                 goto fail;
2701         }
2702
2703         result->transport->transport = NCACN_IP_TCP;
2704
2705         result->binding_handle = rpccli_bh_create(result, NULL, table);
2706         if (result->binding_handle == NULL) {
2707                 TALLOC_FREE(result);
2708                 return NT_STATUS_NO_MEMORY;
2709         }
2710
2711         *presult = result;
2712         return NT_STATUS_OK;
2713
2714  fail:
2715         TALLOC_FREE(result);
2716         return status;
2717 }
2718
2719 /**
2720  * Determine the tcp port on which a dcerpc interface is listening
2721  * for the ncacn_ip_tcp transport via the endpoint mapper of the
2722  * target host.
2723  */
2724 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2725                                       const struct sockaddr_storage *addr,
2726                                       const struct ndr_interface_table *table,
2727                                       uint16_t *pport)
2728 {
2729         NTSTATUS status;
2730         struct rpc_pipe_client *epm_pipe = NULL;
2731         struct dcerpc_binding_handle *epm_handle = NULL;
2732         struct pipe_auth_data *auth = NULL;
2733         struct dcerpc_binding *map_binding = NULL;
2734         struct dcerpc_binding *res_binding = NULL;
2735         enum dcerpc_transport_t transport;
2736         const char *endpoint = NULL;
2737         struct epm_twr_t *map_tower = NULL;
2738         struct epm_twr_t *res_towers = NULL;
2739         struct policy_handle *entry_handle = NULL;
2740         uint32_t num_towers = 0;
2741         uint32_t max_towers = 1;
2742         struct epm_twr_p_t towers;
2743         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2744         uint32_t result = 0;
2745
2746         if (pport == NULL) {
2747                 status = NT_STATUS_INVALID_PARAMETER;
2748                 goto done;
2749         }
2750
2751         if (ndr_syntax_id_equal(&table->syntax_id,
2752                                 &ndr_table_epmapper.syntax_id)) {
2753                 *pport = 135;
2754                 status = NT_STATUS_OK;
2755                 goto done;
2756         }
2757
2758         /* open the connection to the endpoint mapper */
2759         status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2760                                         &ndr_table_epmapper,
2761                                         &epm_pipe);
2762
2763         if (!NT_STATUS_IS_OK(status)) {
2764                 goto done;
2765         }
2766         epm_handle = epm_pipe->binding_handle;
2767
2768         status = rpccli_anon_bind_data(tmp_ctx, &auth);
2769         if (!NT_STATUS_IS_OK(status)) {
2770                 goto done;
2771         }
2772
2773         status = rpc_pipe_bind(epm_pipe, auth);
2774         if (!NT_STATUS_IS_OK(status)) {
2775                 goto done;
2776         }
2777
2778         /* create tower for asking the epmapper */
2779
2780         status = dcerpc_parse_binding(tmp_ctx, "ncacn_ip_tcp:[135]",
2781                                       &map_binding);
2782         if (!NT_STATUS_IS_OK(status)) {
2783                 goto done;
2784         }
2785
2786         status = dcerpc_binding_set_abstract_syntax(map_binding,
2787                                                     &table->syntax_id);
2788         if (!NT_STATUS_IS_OK(status)) {
2789                 goto done;
2790         }
2791
2792         map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
2793         if (map_tower == NULL) {
2794                 status = NT_STATUS_NO_MEMORY;
2795                 goto done;
2796         }
2797
2798         status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2799                                             &(map_tower->tower));
2800         if (!NT_STATUS_IS_OK(status)) {
2801                 goto done;
2802         }
2803
2804         /* allocate further parameters for the epm_Map call */
2805
2806         res_towers = talloc_array(tmp_ctx, struct epm_twr_t, max_towers);
2807         if (res_towers == NULL) {
2808                 status = NT_STATUS_NO_MEMORY;
2809                 goto done;
2810         }
2811         towers.twr = res_towers;
2812
2813         entry_handle = talloc_zero(tmp_ctx, struct policy_handle);
2814         if (entry_handle == NULL) {
2815                 status = NT_STATUS_NO_MEMORY;
2816                 goto done;
2817         }
2818
2819         /* ask the endpoint mapper for the port */
2820
2821         status = dcerpc_epm_Map(epm_handle,
2822                                 tmp_ctx,
2823                                 discard_const_p(struct GUID,
2824                                               &(table->syntax_id.uuid)),
2825                                 map_tower,
2826                                 entry_handle,
2827                                 max_towers,
2828                                 &num_towers,
2829                                 &towers,
2830                                 &result);
2831
2832         if (!NT_STATUS_IS_OK(status)) {
2833                 goto done;
2834         }
2835
2836         if (result != EPMAPPER_STATUS_OK) {
2837                 status = NT_STATUS_UNSUCCESSFUL;
2838                 goto done;
2839         }
2840
2841         if (num_towers != 1) {
2842                 status = NT_STATUS_UNSUCCESSFUL;
2843                 goto done;
2844         }
2845
2846         /* extract the port from the answer */
2847
2848         status = dcerpc_binding_from_tower(tmp_ctx,
2849                                            &(towers.twr->tower),
2850                                            &res_binding);
2851         if (!NT_STATUS_IS_OK(status)) {
2852                 goto done;
2853         }
2854
2855         transport = dcerpc_binding_get_transport(res_binding);
2856         endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
2857
2858         /* are further checks here necessary? */
2859         if (transport != NCACN_IP_TCP) {
2860                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2861                 goto done;
2862         }
2863
2864         if (endpoint == NULL) {
2865                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2866                 goto done;
2867         }
2868
2869         *pport = (uint16_t)atoi(endpoint);
2870
2871 done:
2872         TALLOC_FREE(tmp_ctx);
2873         return status;
2874 }
2875
2876 /**
2877  * Create a rpc pipe client struct, connecting to a host via tcp.
2878  * The port is determined by asking the endpoint mapper on the given
2879  * host.
2880  */
2881 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2882                            const struct sockaddr_storage *addr,
2883                            const struct ndr_interface_table *table,
2884                            struct rpc_pipe_client **presult)
2885 {
2886         NTSTATUS status;
2887         uint16_t port = 0;
2888
2889         status = rpc_pipe_get_tcp_port(host, addr, table, &port);
2890         if (!NT_STATUS_IS_OK(status)) {
2891                 return status;
2892         }
2893
2894         return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2895                                       table, presult);
2896 }
2897
2898 /********************************************************************
2899  Create a rpc pipe client struct, connecting to a unix domain socket
2900  ********************************************************************/
2901 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2902                                const struct ndr_interface_table *table,
2903                                struct rpc_pipe_client **presult)
2904 {
2905         struct rpc_pipe_client *result;
2906         struct sockaddr_un addr;
2907         NTSTATUS status;
2908         int fd;
2909         socklen_t salen;
2910
2911         result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2912         if (result == NULL) {
2913                 return NT_STATUS_NO_MEMORY;
2914         }
2915
2916         result->abstract_syntax = table->syntax_id;
2917         result->transfer_syntax = ndr_transfer_syntax_ndr;
2918
2919         result->desthost = get_myname(result);
2920         if (result->desthost == NULL) {
2921                 status = NT_STATUS_NO_MEMORY;
2922                 goto fail;
2923         }
2924
2925         result->srv_name_slash = talloc_asprintf_strupper_m(
2926                 result, "\\\\%s", result->desthost);
2927         if (result->srv_name_slash == NULL) {
2928                 status = NT_STATUS_NO_MEMORY;
2929                 goto fail;
2930         }
2931
2932         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2933
2934         fd = socket(AF_UNIX, SOCK_STREAM, 0);
2935         if (fd == -1) {
2936                 status = map_nt_error_from_unix(errno);
2937                 goto fail;
2938         }
2939
2940         ZERO_STRUCT(addr);
2941         addr.sun_family = AF_UNIX;
2942         strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2943         salen = sizeof(struct sockaddr_un);
2944
2945         if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
2946                 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2947                           strerror(errno)));
2948                 close(fd);
2949                 return map_nt_error_from_unix(errno);
2950         }
2951
2952         status = rpc_transport_sock_init(result, fd, &result->transport);
2953         if (!NT_STATUS_IS_OK(status)) {
2954                 close(fd);
2955                 goto fail;
2956         }
2957
2958         result->transport->transport = NCALRPC;
2959
2960         result->binding_handle = rpccli_bh_create(result, NULL, table);
2961         if (result->binding_handle == NULL) {
2962                 TALLOC_FREE(result);
2963                 return NT_STATUS_NO_MEMORY;
2964         }
2965
2966         *presult = result;
2967         return NT_STATUS_OK;
2968
2969  fail:
2970         TALLOC_FREE(result);
2971         return status;
2972 }
2973
2974 struct rpc_pipe_client_np_ref {
2975         struct cli_state *cli;
2976         struct rpc_pipe_client *pipe;
2977 };
2978
2979 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2980 {
2981         DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2982         return 0;
2983 }
2984
2985 /****************************************************************************
2986  Open a named pipe over SMB to a remote server.
2987  *
2988  * CAVEAT CALLER OF THIS FUNCTION:
2989  *    The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2990  *    so be sure that this function is called AFTER any structure (vs pointer)
2991  *    assignment of the cli.  In particular, libsmbclient does structure
2992  *    assignments of cli, which invalidates the data in the returned
2993  *    rpc_pipe_client if this function is called before the structure assignment
2994  *    of cli.
2995  * 
2996  ****************************************************************************/
2997
2998 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2999                                  const struct ndr_interface_table *table,
3000                                  struct rpc_pipe_client **presult)
3001 {
3002         struct rpc_pipe_client *result;
3003         NTSTATUS status;
3004         struct rpc_pipe_client_np_ref *np_ref;
3005
3006         /* sanity check to protect against crashes */
3007
3008         if ( !cli ) {
3009                 return NT_STATUS_INVALID_HANDLE;
3010         }
3011
3012         result = talloc_zero(NULL, struct rpc_pipe_client);
3013         if (result == NULL) {
3014                 return NT_STATUS_NO_MEMORY;
3015         }
3016
3017         result->abstract_syntax = table->syntax_id;
3018         result->transfer_syntax = ndr_transfer_syntax_ndr;
3019
3020         result->desthost = talloc_strdup(
3021                 result, smbXcli_conn_remote_name(cli->conn));
3022         if (result->desthost == NULL) {
3023                 TALLOC_FREE(result);
3024                 return NT_STATUS_NO_MEMORY;
3025         }
3026
3027         result->srv_name_slash = talloc_asprintf_strupper_m(
3028                 result, "\\\\%s", result->desthost);
3029         if (result->srv_name_slash == NULL) {
3030                 TALLOC_FREE(result);
3031                 return NT_STATUS_NO_MEMORY;
3032         }
3033
3034         result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3035
3036         status = rpc_transport_np_init(result, cli, table,
3037                                        &result->transport);
3038         if (!NT_STATUS_IS_OK(status)) {
3039                 TALLOC_FREE(result);
3040                 return status;
3041         }
3042
3043         result->transport->transport = NCACN_NP;
3044
3045         np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3046         if (np_ref == NULL) {
3047                 TALLOC_FREE(result);
3048                 return NT_STATUS_NO_MEMORY;
3049         }
3050         np_ref->cli = cli;
3051         np_ref->pipe = result;
3052
3053         DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3054         talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3055
3056         result->binding_handle = rpccli_bh_create(result, NULL, table);
3057         if (result->binding_handle == NULL) {
3058                 TALLOC_FREE(result);
3059                 return NT_STATUS_NO_MEMORY;
3060         }
3061
3062         *presult = result;
3063         return NT_STATUS_OK;
3064 }
3065
3066 /****************************************************************************
3067  Open a pipe to a remote server.
3068  ****************************************************************************/
3069
3070 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3071                                   enum dcerpc_transport_t transport,
3072                                   const struct ndr_interface_table *table,
3073                                   struct rpc_pipe_client **presult)
3074 {
3075         switch (transport) {
3076         case NCACN_IP_TCP:
3077                 return rpc_pipe_open_tcp(NULL,
3078                                          smbXcli_conn_remote_name(cli->conn),
3079                                          smbXcli_conn_remote_sockaddr(cli->conn),
3080                                          table, presult);
3081         case NCACN_NP:
3082                 return rpc_pipe_open_np(cli, table, presult);
3083         default:
3084                 return NT_STATUS_NOT_IMPLEMENTED;
3085         }
3086 }
3087
3088 /****************************************************************************
3089  Open a named pipe to an SMB server and bind anonymously.
3090  ****************************************************************************/
3091
3092 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3093                                             enum dcerpc_transport_t transport,
3094                                             const struct ndr_interface_table *table,
3095                                             struct rpc_pipe_client **presult)
3096 {
3097         struct rpc_pipe_client *result;
3098         struct pipe_auth_data *auth;
3099         NTSTATUS status;
3100
3101         status = cli_rpc_pipe_open(cli, transport, table, &result);
3102         if (!NT_STATUS_IS_OK(status)) {
3103                 return status;
3104         }
3105
3106         status = rpccli_anon_bind_data(result, &auth);
3107         if (!NT_STATUS_IS_OK(status)) {
3108                 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3109                           nt_errstr(status)));
3110                 TALLOC_FREE(result);
3111                 return status;
3112         }
3113
3114         /*
3115          * This is a bit of an abstraction violation due to the fact that an
3116          * anonymous bind on an authenticated SMB inherits the user/domain
3117          * from the enclosing SMB creds
3118          */
3119
3120         if (transport == NCACN_NP) {
3121                 struct smbXcli_session *session;
3122
3123                 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3124                         session = cli->smb2.session;
3125                 } else {
3126                         session = cli->smb1.session;
3127                 }
3128
3129                 status = smbXcli_session_application_key(session, auth,
3130                                                 &auth->transport_session_key);
3131                 if (!NT_STATUS_IS_OK(status)) {
3132                         auth->transport_session_key = data_blob_null;
3133                 }
3134         }
3135
3136         status = rpc_pipe_bind(result, auth);
3137         if (!NT_STATUS_IS_OK(status)) {
3138                 int lvl = 0;
3139                 if (ndr_syntax_id_equal(&table->syntax_id,
3140                                         &ndr_table_dssetup.syntax_id)) {
3141                         /* non AD domains just don't have this pipe, avoid
3142                          * level 0 statement in that case - gd */
3143                         lvl = 3;
3144                 }
3145                 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3146                             "%s failed with error %s\n",
3147                             table->name,
3148                             nt_errstr(status) ));
3149                 TALLOC_FREE(result);
3150                 return status;
3151         }
3152
3153         DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3154                   "%s and bound anonymously.\n",
3155                   table->name,
3156                   result->desthost));
3157
3158         *presult = result;
3159         return NT_STATUS_OK;
3160 }
3161
3162 /****************************************************************************
3163  ****************************************************************************/
3164
3165 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3166                                   const struct ndr_interface_table *table,
3167                                   struct rpc_pipe_client **presult)
3168 {
3169         return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3170                                                   table, presult);
3171 }
3172
3173 /****************************************************************************
3174  Open a named pipe to an SMB server and bind using the mech specified
3175
3176  This routine references the creds pointer that is passed in
3177  ****************************************************************************/
3178
3179 NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
3180                                       const struct ndr_interface_table *table,
3181                                       enum dcerpc_transport_t transport,
3182                                       enum dcerpc_AuthType auth_type,
3183                                       enum dcerpc_AuthLevel auth_level,
3184                                       const char *server,
3185                                       struct cli_credentials *creds,
3186                                       struct rpc_pipe_client **presult)
3187 {
3188         struct rpc_pipe_client *result;
3189         struct pipe_auth_data *auth = NULL;
3190         const char *target_service = table->authservices->names[0];
3191         NTSTATUS status;
3192
3193         status = cli_rpc_pipe_open(cli, transport, table, &result);
3194         if (!NT_STATUS_IS_OK(status)) {
3195                 return status;
3196         }
3197
3198         status = rpccli_generic_bind_data_from_creds(result,
3199                                                      auth_type, auth_level,
3200                                                      server, target_service,
3201                                                      creds,
3202                                                      &auth);
3203         if (!NT_STATUS_IS_OK(status)) {
3204                 DBG_ERR("rpccli_generic_bind_data_from_creds returned %s\n",
3205                         nt_errstr(status));
3206                 goto err;
3207         }
3208
3209         status = rpc_pipe_bind(result, auth);
3210         if (!NT_STATUS_IS_OK(status)) {
3211                 DBG_ERR("cli_rpc_pipe_bind failed with error %s\n",
3212                         nt_errstr(status));
3213                 goto err;
3214         }
3215
3216         DBG_DEBUG("opened pipe %s to machine %s and bound as user %s.\n",
3217                   table->name,
3218                   result->desthost,
3219                   cli_credentials_get_unparsed_name(creds, talloc_tos()));
3220
3221         *presult = result;
3222         return NT_STATUS_OK;
3223
3224   err:
3225
3226         TALLOC_FREE(result);
3227         return status;
3228 }
3229
3230 /****************************************************************************
3231  Open a named pipe to an SMB server and bind using the mech specified
3232
3233  This routine steals the creds pointer that is passed in
3234  ****************************************************************************/
3235
3236 NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
3237                                         const struct ndr_interface_table *table,
3238                                         enum dcerpc_transport_t transport,
3239                                         enum dcerpc_AuthType auth_type,
3240                                         enum dcerpc_AuthLevel auth_level,
3241                                         const char *server,
3242                                         const char *domain,
3243                                         const char *username,
3244                                         const char *password,
3245                                         struct rpc_pipe_client **presult)
3246 {
3247         struct rpc_pipe_client *result;
3248         struct pipe_auth_data *auth = NULL;
3249         const char *target_service = table->authservices->names[0];
3250         
3251         NTSTATUS status;
3252
3253         status = cli_rpc_pipe_open(cli, transport, table, &result);
3254         if (!NT_STATUS_IS_OK(status)) {
3255                 return status;
3256         }
3257
3258         status = rpccli_generic_bind_data(result,
3259                                           auth_type, auth_level,
3260                                           server, target_service,
3261                                           domain, username, password, 
3262                                           CRED_AUTO_USE_KERBEROS,
3263                                           NULL,
3264                                           &auth);
3265         if (!NT_STATUS_IS_OK(status)) {
3266                 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3267                           nt_errstr(status)));
3268                 goto err;
3269         }
3270
3271         status = rpc_pipe_bind(result, auth);
3272         if (!NT_STATUS_IS_OK(status)) {
3273                 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
3274                         nt_errstr(status) ));
3275                 goto err;
3276         }
3277
3278         DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
3279                 "machine %s and bound as user %s\\%s.\n", table->name,
3280                   result->desthost, domain, username));
3281
3282         *presult = result;
3283         return NT_STATUS_OK;
3284
3285   err:
3286
3287         TALLOC_FREE(result);
3288         return status;
3289 }
3290
3291 NTSTATUS cli_rpc_pipe_open_bind_schannel(
3292         struct cli_state *cli,
3293         const struct ndr_interface_table *table,
3294         enum dcerpc_transport_t transport,
3295         struct netlogon_creds_cli_context *netlogon_creds,
3296         struct rpc_pipe_client **_rpccli)
3297 {
3298         struct rpc_pipe_client *rpccli;
3299         struct pipe_auth_data *rpcauth;
3300         const char *target_service = table->authservices->names[0];
3301         struct cli_credentials *cli_creds;
3302         enum dcerpc_AuthLevel auth_level;
3303         NTSTATUS status;
3304
3305         status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
3306         if (!NT_STATUS_IS_OK(status)) {
3307                 return status;
3308         }
3309
3310         auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
3311
3312         status = netlogon_creds_bind_cli_credentials(
3313                 netlogon_creds, rpccli, &cli_creds);
3314         if (!NT_STATUS_IS_OK(status)) {
3315                 DBG_DEBUG("netlogon_creds_bind_cli_credentials failed: %s\n",
3316                           nt_errstr(status));
3317                 TALLOC_FREE(rpccli);
3318                 return status;
3319         }
3320
3321         status = rpccli_generic_bind_data_from_creds(rpccli,
3322                                                      DCERPC_AUTH_TYPE_SCHANNEL,
3323                                                      auth_level,
3324                                                      rpccli->desthost,
3325                                                      target_service,
3326                                                      cli_creds,
3327                                                      &rpcauth);
3328         if (!NT_STATUS_IS_OK(status)) {
3329                 DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
3330                           nt_errstr(status)));
3331                 TALLOC_FREE(rpccli);
3332                 return status;
3333         }
3334
3335         status = rpc_pipe_bind(rpccli, rpcauth);
3336
3337         /* No TALLOC_FREE, gensec takes references */
3338         talloc_unlink(rpccli, cli_creds);
3339         cli_creds = NULL;
3340
3341         if (!NT_STATUS_IS_OK(status)) {
3342                 DBG_DEBUG("rpc_pipe_bind failed with error %s\n",
3343                           nt_errstr(status));
3344                 TALLOC_FREE(rpccli);
3345                 return status;
3346         }
3347
3348         *_rpccli = rpccli;
3349
3350         return NT_STATUS_OK;
3351 }
3352
3353 NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
3354                                                const struct ndr_interface_table *table,
3355                                                enum dcerpc_transport_t transport,
3356                                                struct netlogon_creds_cli_context *netlogon_creds,
3357                                                struct rpc_pipe_client **_rpccli)
3358 {
3359         TALLOC_CTX *frame = talloc_stackframe();
3360         struct rpc_pipe_client *rpccli;
3361         struct netlogon_creds_cli_lck *lck;
3362         NTSTATUS status;
3363
3364         status = netlogon_creds_cli_lck(
3365                 netlogon_creds, NETLOGON_CREDS_CLI_LCK_EXCLUSIVE,
3366                 frame, &lck);
3367         if (!NT_STATUS_IS_OK(status)) {
3368                 DBG_WARNING("netlogon_creds_cli_lck returned %s\n",
3369                             nt_errstr(status));
3370                 TALLOC_FREE(frame);
3371                 return status;
3372         }
3373
3374         status = cli_rpc_pipe_open_bind_schannel(
3375                 cli, table, transport, netlogon_creds, &rpccli);
3376         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3377                 netlogon_creds_cli_delete_lck(netlogon_creds);
3378         }
3379         if (!NT_STATUS_IS_OK(status)) {
3380                 DBG_DEBUG("cli_rpc_pipe_open_bind_schannel failed: %s\n",
3381                           nt_errstr(status));
3382                 TALLOC_FREE(frame);
3383                 return status;
3384         }
3385
3386         if (ndr_syntax_id_equal(&table->syntax_id,
3387                                 &ndr_table_netlogon.syntax_id)) {
3388                 status =&nbs