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