tests/krb5: Fix sha1 checksum type
[Samba.git] / source3 / rpc_client / cli_pipe.c
blob8227ef0b0bd1394c6b3d69c781776c53783f5349
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.
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.
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.
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/>.
22 #include "includes.h"
23 #include "libsmb/namequery.h"
24 #include "../lib/util/tevent_ntstatus.h"
25 #include "librpc/gen_ndr/ndr_epmapper_c.h"
26 #include "../librpc/gen_ndr/ndr_dssetup.h"
27 #include "../libcli/auth/schannel.h"
28 #include "../libcli/auth/netlogon_creds_cli.h"
29 #include "auth_generic.h"
30 #include "librpc/gen_ndr/ndr_dcerpc.h"
31 #include "librpc/gen_ndr/ndr_netlogon_c.h"
32 #include "librpc/rpc/dcerpc.h"
33 #include "rpc_dce.h"
34 #include "cli_pipe.h"
35 #include "libsmb/libsmb.h"
36 #include "auth/gensec/gensec.h"
37 #include "auth/credentials/credentials.h"
38 #include "../libcli/smb/smbXcli_base.h"
40 #undef DBGC_CLASS
41 #define DBGC_CLASS DBGC_RPC_CLI
43 /********************************************************************
44 Pipe description for a DEBUG
45 ********************************************************************/
46 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
47 struct rpc_pipe_client *cli)
49 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
50 if (result == NULL) {
51 return "pipe";
53 return result;
56 /********************************************************************
57 Rpc pipe call id.
58 ********************************************************************/
60 static uint32_t get_rpc_call_id(void)
62 static uint32_t call_id = 0;
63 return ++call_id;
66 /*******************************************************************
67 Use SMBreadX to get rest of one fragment's worth of rpc data.
68 Reads the whole size or give an error message
69 ********************************************************************/
71 struct rpc_read_state {
72 struct tevent_context *ev;
73 struct rpc_cli_transport *transport;
74 uint8_t *data;
75 size_t size;
76 size_t num_read;
79 static void rpc_read_done(struct tevent_req *subreq);
81 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
82 struct tevent_context *ev,
83 struct rpc_cli_transport *transport,
84 uint8_t *data, size_t size)
86 struct tevent_req *req, *subreq;
87 struct rpc_read_state *state;
89 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
90 if (req == NULL) {
91 return NULL;
93 state->ev = ev;
94 state->transport = transport;
95 state->data = data;
96 state->size = size;
97 state->num_read = 0;
99 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
101 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
102 transport->priv);
103 if (subreq == NULL) {
104 goto fail;
106 tevent_req_set_callback(subreq, rpc_read_done, req);
107 return req;
109 fail:
110 TALLOC_FREE(req);
111 return NULL;
114 static void rpc_read_done(struct tevent_req *subreq)
116 struct tevent_req *req = tevent_req_callback_data(
117 subreq, struct tevent_req);
118 struct rpc_read_state *state = tevent_req_data(
119 req, struct rpc_read_state);
120 NTSTATUS status;
121 ssize_t received;
123 status = state->transport->read_recv(subreq, &received);
124 TALLOC_FREE(subreq);
125 if (!NT_STATUS_IS_OK(status)) {
126 tevent_req_nterror(req, status);
127 return;
130 state->num_read += received;
131 if (state->num_read == state->size) {
132 tevent_req_done(req);
133 return;
136 subreq = state->transport->read_send(state, state->ev,
137 state->data + state->num_read,
138 state->size - state->num_read,
139 state->transport->priv);
140 if (tevent_req_nomem(subreq, req)) {
141 return;
143 tevent_req_set_callback(subreq, rpc_read_done, req);
146 static NTSTATUS rpc_read_recv(struct tevent_req *req)
148 return tevent_req_simple_recv_ntstatus(req);
151 struct rpc_write_state {
152 struct tevent_context *ev;
153 struct rpc_cli_transport *transport;
154 const uint8_t *data;
155 size_t size;
156 size_t num_written;
159 static void rpc_write_done(struct tevent_req *subreq);
161 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
162 struct tevent_context *ev,
163 struct rpc_cli_transport *transport,
164 const uint8_t *data, size_t size)
166 struct tevent_req *req, *subreq;
167 struct rpc_write_state *state;
169 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
170 if (req == NULL) {
171 return NULL;
173 state->ev = ev;
174 state->transport = transport;
175 state->data = data;
176 state->size = size;
177 state->num_written = 0;
179 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
181 subreq = transport->write_send(state, ev, data, size, transport->priv);
182 if (subreq == NULL) {
183 goto fail;
185 tevent_req_set_callback(subreq, rpc_write_done, req);
186 return req;
187 fail:
188 TALLOC_FREE(req);
189 return NULL;
192 static void rpc_write_done(struct tevent_req *subreq)
194 struct tevent_req *req = tevent_req_callback_data(
195 subreq, struct tevent_req);
196 struct rpc_write_state *state = tevent_req_data(
197 req, struct rpc_write_state);
198 NTSTATUS status;
199 ssize_t written;
201 status = state->transport->write_recv(subreq, &written);
202 TALLOC_FREE(subreq);
203 if (!NT_STATUS_IS_OK(status)) {
204 tevent_req_nterror(req, status);
205 return;
208 state->num_written += written;
210 if (state->num_written == state->size) {
211 tevent_req_done(req);
212 return;
215 subreq = state->transport->write_send(state, state->ev,
216 state->data + state->num_written,
217 state->size - state->num_written,
218 state->transport->priv);
219 if (tevent_req_nomem(subreq, req)) {
220 return;
222 tevent_req_set_callback(subreq, rpc_write_done, req);
225 static NTSTATUS rpc_write_recv(struct tevent_req *req)
227 return tevent_req_simple_recv_ntstatus(req);
231 /****************************************************************************
232 Try and get a PDU's worth of data from current_pdu. If not, then read more
233 from the wire.
234 ****************************************************************************/
236 struct get_complete_frag_state {
237 struct tevent_context *ev;
238 struct rpc_pipe_client *cli;
239 uint16_t frag_len;
240 DATA_BLOB *pdu;
243 static void get_complete_frag_got_header(struct tevent_req *subreq);
244 static void get_complete_frag_got_rest(struct tevent_req *subreq);
246 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
247 struct tevent_context *ev,
248 struct rpc_pipe_client *cli,
249 DATA_BLOB *pdu)
251 struct tevent_req *req, *subreq;
252 struct get_complete_frag_state *state;
253 size_t received;
254 NTSTATUS status;
256 req = tevent_req_create(mem_ctx, &state,
257 struct get_complete_frag_state);
258 if (req == NULL) {
259 return NULL;
261 state->ev = ev;
262 state->cli = cli;
263 state->frag_len = RPC_HEADER_LEN;
264 state->pdu = pdu;
266 received = pdu->length;
267 if (received < RPC_HEADER_LEN) {
268 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
269 status = NT_STATUS_NO_MEMORY;
270 goto post_status;
272 subreq = rpc_read_send(state, state->ev,
273 state->cli->transport,
274 pdu->data + received,
275 RPC_HEADER_LEN - received);
276 if (subreq == NULL) {
277 status = NT_STATUS_NO_MEMORY;
278 goto post_status;
280 tevent_req_set_callback(subreq, get_complete_frag_got_header,
281 req);
282 return req;
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);
292 * Ensure we have frag_len bytes of data.
294 if (received < state->frag_len) {
295 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
296 status = NT_STATUS_NO_MEMORY;
297 goto post_status;
299 subreq = rpc_read_send(state, state->ev,
300 state->cli->transport,
301 pdu->data + received,
302 state->frag_len - received);
303 if (subreq == NULL) {
304 status = NT_STATUS_NO_MEMORY;
305 goto post_status;
307 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
308 req);
309 return req;
312 status = NT_STATUS_OK;
313 post_status:
314 if (NT_STATUS_IS_OK(status)) {
315 tevent_req_done(req);
316 } else {
317 tevent_req_nterror(req, status);
319 return tevent_req_post(req, ev);
322 static void get_complete_frag_got_header(struct tevent_req *subreq)
324 struct tevent_req *req = tevent_req_callback_data(
325 subreq, struct tevent_req);
326 struct get_complete_frag_state *state = tevent_req_data(
327 req, struct get_complete_frag_state);
328 NTSTATUS status;
330 status = rpc_read_recv(subreq);
331 TALLOC_FREE(subreq);
332 if (!NT_STATUS_IS_OK(status)) {
333 tevent_req_nterror(req, status);
334 return;
337 state->frag_len = dcerpc_get_frag_length(state->pdu);
338 if (state->frag_len < RPC_HEADER_LEN) {
339 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
340 return;
343 if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
344 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
345 return;
349 * We're here in this piece of code because we've read exactly
350 * RPC_HEADER_LEN bytes into state->pdu.
353 subreq = rpc_read_send(state, state->ev, state->cli->transport,
354 state->pdu->data + RPC_HEADER_LEN,
355 state->frag_len - RPC_HEADER_LEN);
356 if (tevent_req_nomem(subreq, req)) {
357 return;
359 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
362 static void get_complete_frag_got_rest(struct tevent_req *subreq)
364 struct tevent_req *req = tevent_req_callback_data(
365 subreq, struct tevent_req);
366 NTSTATUS status;
368 status = rpc_read_recv(subreq);
369 TALLOC_FREE(subreq);
370 if (!NT_STATUS_IS_OK(status)) {
371 tevent_req_nterror(req, status);
372 return;
374 tevent_req_done(req);
377 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
379 return tevent_req_simple_recv_ntstatus(req);
382 /****************************************************************************
383 Do basic authentication checks on an incoming pdu.
384 ****************************************************************************/
386 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
387 struct rpc_pipe_client *cli,
388 struct ncacn_packet *pkt,
389 DATA_BLOB *pdu,
390 uint8_t expected_pkt_type,
391 uint32_t call_id,
392 DATA_BLOB *rdata,
393 DATA_BLOB *reply_pdu)
395 const struct dcerpc_response *r = NULL;
396 DATA_BLOB tmp_stub = data_blob_null;
397 NTSTATUS ret;
400 * Point the return values at the real data including the RPC
401 * header. Just in case the caller wants it.
403 *rdata = *pdu;
405 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
406 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
408 * TODO: do we still need this hack which was introduced
409 * in commit a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0.
411 * I don't even know what AS/U might be...
413 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
414 "fragment first/last ON.\n"));
415 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
418 /* Ensure we have the correct type. */
419 switch (pkt->ptype) {
420 case DCERPC_PKT_BIND_NAK:
421 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
422 rpccli_pipe_txt(talloc_tos(), cli)));
424 ret = dcerpc_verify_ncacn_packet_header(pkt,
425 DCERPC_PKT_BIND_NAK,
426 0, /* max_auth_info */
427 DCERPC_PFC_FLAG_FIRST |
428 DCERPC_PFC_FLAG_LAST,
429 0); /* optional flags */
430 if (!NT_STATUS_IS_OK(ret)) {
431 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
432 "RPC packet type - %u, expected %u: %s\n",
433 rpccli_pipe_txt(talloc_tos(), cli),
434 pkt->ptype, expected_pkt_type,
435 nt_errstr(ret)));
436 NDR_PRINT_DEBUG(ncacn_packet, pkt);
437 return ret;
440 /* Use this for now... */
441 return NT_STATUS_NETWORK_ACCESS_DENIED;
443 case DCERPC_PKT_BIND_ACK:
444 ret = dcerpc_verify_ncacn_packet_header(pkt,
445 expected_pkt_type,
446 pkt->u.bind_ack.auth_info.length,
447 DCERPC_PFC_FLAG_FIRST |
448 DCERPC_PFC_FLAG_LAST,
449 DCERPC_PFC_FLAG_CONC_MPX |
450 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
451 if (!NT_STATUS_IS_OK(ret)) {
452 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
453 "RPC packet type - %u, expected %u: %s\n",
454 rpccli_pipe_txt(talloc_tos(), cli),
455 pkt->ptype, expected_pkt_type,
456 nt_errstr(ret)));
457 NDR_PRINT_DEBUG(ncacn_packet, pkt);
458 return ret;
461 break;
463 case DCERPC_PKT_ALTER_RESP:
464 ret = dcerpc_verify_ncacn_packet_header(pkt,
465 expected_pkt_type,
466 pkt->u.alter_resp.auth_info.length,
467 DCERPC_PFC_FLAG_FIRST |
468 DCERPC_PFC_FLAG_LAST,
469 DCERPC_PFC_FLAG_CONC_MPX |
470 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
471 if (!NT_STATUS_IS_OK(ret)) {
472 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
473 "RPC packet type - %u, expected %u: %s\n",
474 rpccli_pipe_txt(talloc_tos(), cli),
475 pkt->ptype, expected_pkt_type,
476 nt_errstr(ret)));
477 NDR_PRINT_DEBUG(ncacn_packet, pkt);
478 return ret;
481 break;
483 case DCERPC_PKT_RESPONSE:
485 r = &pkt->u.response;
487 ret = dcerpc_verify_ncacn_packet_header(pkt,
488 expected_pkt_type,
489 r->stub_and_verifier.length,
490 0, /* required_flags */
491 DCERPC_PFC_FLAG_FIRST |
492 DCERPC_PFC_FLAG_LAST);
493 if (!NT_STATUS_IS_OK(ret)) {
494 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
495 "RPC packet type - %u, expected %u: %s\n",
496 rpccli_pipe_txt(talloc_tos(), cli),
497 pkt->ptype, expected_pkt_type,
498 nt_errstr(ret)));
499 NDR_PRINT_DEBUG(ncacn_packet, pkt);
500 return ret;
503 tmp_stub.data = r->stub_and_verifier.data;
504 tmp_stub.length = r->stub_and_verifier.length;
506 /* Here's where we deal with incoming sign/seal. */
507 ret = dcerpc_check_auth(cli->auth, pkt,
508 &tmp_stub,
509 DCERPC_RESPONSE_LENGTH,
510 pdu);
511 if (!NT_STATUS_IS_OK(ret)) {
512 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
513 "RPC packet type - %u, expected %u: %s\n",
514 rpccli_pipe_txt(talloc_tos(), cli),
515 pkt->ptype, expected_pkt_type,
516 nt_errstr(ret)));
517 NDR_PRINT_DEBUG(ncacn_packet, pkt);
518 return ret;
521 /* Point the return values at the NDR data. */
522 *rdata = tmp_stub;
524 DEBUG(10, ("Got pdu len %lu, data_len %lu\n",
525 (long unsigned int)pdu->length,
526 (long unsigned int)rdata->length));
529 * If this is the first reply, and the allocation hint is
530 * reasonable, try and set up the reply_pdu DATA_BLOB to the
531 * correct size.
534 if ((reply_pdu->length == 0) &&
535 r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
536 if (!data_blob_realloc(mem_ctx, reply_pdu,
537 r->alloc_hint)) {
538 DEBUG(0, ("reply alloc hint %d too "
539 "large to allocate\n",
540 (int)r->alloc_hint));
541 return NT_STATUS_NO_MEMORY;
545 break;
547 case DCERPC_PKT_FAULT:
549 ret = dcerpc_verify_ncacn_packet_header(pkt,
550 DCERPC_PKT_FAULT,
551 0, /* max_auth_info */
552 DCERPC_PFC_FLAG_FIRST |
553 DCERPC_PFC_FLAG_LAST,
554 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
555 if (!NT_STATUS_IS_OK(ret)) {
556 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
557 "RPC packet type - %u, expected %u: %s\n",
558 rpccli_pipe_txt(talloc_tos(), cli),
559 pkt->ptype, expected_pkt_type,
560 nt_errstr(ret)));
561 NDR_PRINT_DEBUG(ncacn_packet, pkt);
562 return ret;
565 DEBUG(1, (__location__ ": RPC fault code %s received "
566 "from %s!\n",
567 dcerpc_errstr(talloc_tos(),
568 pkt->u.fault.status),
569 rpccli_pipe_txt(talloc_tos(), cli)));
571 return dcerpc_fault_to_nt_status(pkt->u.fault.status);
573 default:
574 DEBUG(0, (__location__ "Unknown packet type %u received "
575 "from %s!\n",
576 (unsigned int)pkt->ptype,
577 rpccli_pipe_txt(talloc_tos(), cli)));
578 return NT_STATUS_RPC_PROTOCOL_ERROR;
582 if (pkt->call_id != call_id) {
583 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
584 "RPC call_id - %u, not %u\n",
585 rpccli_pipe_txt(talloc_tos(), cli),
586 pkt->call_id, call_id));
587 return NT_STATUS_RPC_PROTOCOL_ERROR;
590 return NT_STATUS_OK;
593 /****************************************************************************
594 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
595 ****************************************************************************/
597 struct cli_api_pipe_state {
598 struct tevent_context *ev;
599 struct rpc_cli_transport *transport;
600 uint8_t *rdata;
601 uint32_t rdata_len;
604 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
605 static void cli_api_pipe_write_done(struct tevent_req *subreq);
606 static void cli_api_pipe_read_done(struct tevent_req *subreq);
608 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
609 struct tevent_context *ev,
610 struct rpc_cli_transport *transport,
611 uint8_t *data, size_t data_len,
612 uint32_t max_rdata_len)
614 struct tevent_req *req, *subreq;
615 struct cli_api_pipe_state *state;
616 NTSTATUS status;
618 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
619 if (req == NULL) {
620 return NULL;
622 state->ev = ev;
623 state->transport = transport;
625 if (max_rdata_len < RPC_HEADER_LEN) {
627 * For a RPC reply we always need at least RPC_HEADER_LEN
628 * bytes. We check this here because we will receive
629 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
631 status = NT_STATUS_INVALID_PARAMETER;
632 goto post_status;
635 if (transport->trans_send != NULL) {
636 subreq = transport->trans_send(state, ev, data, data_len,
637 max_rdata_len, transport->priv);
638 if (subreq == NULL) {
639 goto fail;
641 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
642 return req;
646 * If the transport does not provide a "trans" routine, i.e. for
647 * example the ncacn_ip_tcp transport, do the write/read step here.
650 subreq = rpc_write_send(state, ev, transport, data, data_len);
651 if (subreq == NULL) {
652 goto fail;
654 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
655 return req;
657 post_status:
658 tevent_req_nterror(req, status);
659 return tevent_req_post(req, ev);
660 fail:
661 TALLOC_FREE(req);
662 return NULL;
665 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
667 struct tevent_req *req = tevent_req_callback_data(
668 subreq, struct tevent_req);
669 struct cli_api_pipe_state *state = tevent_req_data(
670 req, struct cli_api_pipe_state);
671 NTSTATUS status;
673 status = state->transport->trans_recv(subreq, state, &state->rdata,
674 &state->rdata_len);
675 TALLOC_FREE(subreq);
676 if (!NT_STATUS_IS_OK(status)) {
677 tevent_req_nterror(req, status);
678 return;
680 tevent_req_done(req);
683 static void cli_api_pipe_write_done(struct tevent_req *subreq)
685 struct tevent_req *req = tevent_req_callback_data(
686 subreq, struct tevent_req);
687 struct cli_api_pipe_state *state = tevent_req_data(
688 req, struct cli_api_pipe_state);
689 NTSTATUS status;
691 status = rpc_write_recv(subreq);
692 TALLOC_FREE(subreq);
693 if (!NT_STATUS_IS_OK(status)) {
694 tevent_req_nterror(req, status);
695 return;
698 state->rdata = talloc_array(state, uint8_t, RPC_HEADER_LEN);
699 if (tevent_req_nomem(state->rdata, req)) {
700 return;
704 * We don't need to use rpc_read_send here, the upper layer will cope
705 * with a short read, transport->trans_send could also return less
706 * than state->max_rdata_len.
708 subreq = state->transport->read_send(state, state->ev, state->rdata,
709 RPC_HEADER_LEN,
710 state->transport->priv);
711 if (tevent_req_nomem(subreq, req)) {
712 return;
714 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
717 static void cli_api_pipe_read_done(struct tevent_req *subreq)
719 struct tevent_req *req = tevent_req_callback_data(
720 subreq, struct tevent_req);
721 struct cli_api_pipe_state *state = tevent_req_data(
722 req, struct cli_api_pipe_state);
723 NTSTATUS status;
724 ssize_t received;
726 status = state->transport->read_recv(subreq, &received);
727 TALLOC_FREE(subreq);
728 if (!NT_STATUS_IS_OK(status)) {
729 tevent_req_nterror(req, status);
730 return;
732 state->rdata_len = received;
733 tevent_req_done(req);
736 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
737 uint8_t **prdata, uint32_t *prdata_len)
739 struct cli_api_pipe_state *state = tevent_req_data(
740 req, struct cli_api_pipe_state);
741 NTSTATUS status;
743 if (tevent_req_is_nterror(req, &status)) {
744 return status;
747 *prdata = talloc_move(mem_ctx, &state->rdata);
748 *prdata_len = state->rdata_len;
749 return NT_STATUS_OK;
752 /****************************************************************************
753 Send data on an rpc pipe via trans. The data must be the last
754 pdu fragment of an NDR data stream.
756 Receive response data from an rpc pipe, which may be large...
758 Read the first fragment: unfortunately have to use SMBtrans for the first
759 bit, then SMBreadX for subsequent bits.
761 If first fragment received also wasn't the last fragment, continue
762 getting fragments until we _do_ receive the last fragment.
764 Request/Response PDU's look like the following...
766 |<------------------PDU len----------------------------------------------->|
767 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
769 +------------+-----------------+-------------+---------------+-------------+
770 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
771 +------------+-----------------+-------------+---------------+-------------+
773 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
774 signing & sealing being negotiated.
776 ****************************************************************************/
778 struct rpc_api_pipe_state {
779 struct tevent_context *ev;
780 struct rpc_pipe_client *cli;
781 uint8_t expected_pkt_type;
782 uint32_t call_id;
784 DATA_BLOB incoming_frag;
785 struct ncacn_packet *pkt;
787 /* Incoming reply */
788 DATA_BLOB reply_pdu;
789 size_t reply_pdu_offset;
790 uint8_t endianess;
793 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
794 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
795 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq);
797 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
798 struct tevent_context *ev,
799 struct rpc_pipe_client *cli,
800 DATA_BLOB *data, /* Outgoing PDU */
801 uint8_t expected_pkt_type,
802 uint32_t call_id)
804 struct tevent_req *req, *subreq;
805 struct rpc_api_pipe_state *state;
806 uint16_t max_recv_frag;
807 NTSTATUS status;
809 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
810 if (req == NULL) {
811 return NULL;
813 state->ev = ev;
814 state->cli = cli;
815 state->expected_pkt_type = expected_pkt_type;
816 state->call_id = call_id;
817 state->endianess = DCERPC_DREP_LE;
820 * Ensure we're not sending too much.
822 if (data->length > cli->max_xmit_frag) {
823 status = NT_STATUS_INVALID_PARAMETER;
824 goto post_status;
827 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
829 if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
830 subreq = rpc_write_send(state, ev, cli->transport,
831 data->data, data->length);
832 if (subreq == NULL) {
833 goto fail;
835 tevent_req_set_callback(subreq, rpc_api_pipe_auth3_done, req);
836 return req;
839 /* get the header first, then fetch the rest once we have
840 * the frag_length available */
841 max_recv_frag = RPC_HEADER_LEN;
843 subreq = cli_api_pipe_send(state, ev, cli->transport,
844 data->data, data->length, max_recv_frag);
845 if (subreq == NULL) {
846 goto fail;
848 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
849 return req;
851 post_status:
852 tevent_req_nterror(req, status);
853 return tevent_req_post(req, ev);
854 fail:
855 TALLOC_FREE(req);
856 return NULL;
859 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq)
861 struct tevent_req *req =
862 tevent_req_callback_data(subreq,
863 struct tevent_req);
864 NTSTATUS status;
866 status = rpc_write_recv(subreq);
867 TALLOC_FREE(subreq);
868 if (!NT_STATUS_IS_OK(status)) {
869 tevent_req_nterror(req, status);
870 return;
873 tevent_req_done(req);
876 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
878 struct tevent_req *req = tevent_req_callback_data(
879 subreq, struct tevent_req);
880 struct rpc_api_pipe_state *state = tevent_req_data(
881 req, struct rpc_api_pipe_state);
882 NTSTATUS status;
883 uint8_t *rdata = NULL;
884 uint32_t rdata_len = 0;
886 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
887 TALLOC_FREE(subreq);
888 if (!NT_STATUS_IS_OK(status)) {
889 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
890 tevent_req_nterror(req, status);
891 return;
894 if (rdata == NULL) {
895 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
896 rpccli_pipe_txt(talloc_tos(), state->cli)));
897 tevent_req_done(req);
898 return;
902 * Move data on state->incoming_frag.
904 state->incoming_frag.data = talloc_move(state, &rdata);
905 state->incoming_frag.length = rdata_len;
906 if (!state->incoming_frag.data) {
907 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
908 return;
911 /* Ensure we have enough data for a pdu. */
912 subreq = get_complete_frag_send(state, state->ev, state->cli,
913 &state->incoming_frag);
914 if (tevent_req_nomem(subreq, req)) {
915 return;
917 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
920 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
922 struct tevent_req *req = tevent_req_callback_data(
923 subreq, struct tevent_req);
924 struct rpc_api_pipe_state *state = tevent_req_data(
925 req, struct rpc_api_pipe_state);
926 NTSTATUS status;
927 DATA_BLOB rdata = data_blob_null;
929 status = get_complete_frag_recv(subreq);
930 TALLOC_FREE(subreq);
931 if (!NT_STATUS_IS_OK(status)) {
932 DEBUG(5, ("get_complete_frag failed: %s\n",
933 nt_errstr(status)));
934 tevent_req_nterror(req, status);
935 return;
938 state->pkt = talloc(state, struct ncacn_packet);
939 if (!state->pkt) {
941 * TODO: do a real async disconnect ...
943 * For now do it sync...
945 TALLOC_FREE(state->cli->transport);
946 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
947 return;
950 status = dcerpc_pull_ncacn_packet(state->pkt,
951 &state->incoming_frag,
952 state->pkt);
953 if (!NT_STATUS_IS_OK(status)) {
955 * TODO: do a real async disconnect ...
957 * For now do it sync...
959 TALLOC_FREE(state->cli->transport);
960 tevent_req_nterror(req, status);
961 return;
964 if (DEBUGLEVEL >= 10) {
965 NDR_PRINT_DEBUG(ncacn_packet, state->pkt);
968 status = cli_pipe_validate_current_pdu(state,
969 state->cli, state->pkt,
970 &state->incoming_frag,
971 state->expected_pkt_type,
972 state->call_id,
973 &rdata,
974 &state->reply_pdu);
976 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
977 (unsigned)state->incoming_frag.length,
978 (unsigned)state->reply_pdu_offset,
979 nt_errstr(status)));
981 if (state->pkt->ptype != DCERPC_PKT_FAULT && !NT_STATUS_IS_OK(status)) {
983 * TODO: do a real async disconnect ...
985 * For now do it sync...
987 TALLOC_FREE(state->cli->transport);
988 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
990 * TODO: do a real async disconnect ...
992 * For now do it sync...
994 TALLOC_FREE(state->cli->transport);
995 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
997 * TODO: do a real async disconnect ...
999 * For now do it sync...
1001 TALLOC_FREE(state->cli->transport);
1003 if (!NT_STATUS_IS_OK(status)) {
1004 tevent_req_nterror(req, status);
1005 return;
1008 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
1009 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
1011 * Set the data type correctly for big-endian data on the
1012 * first packet.
1014 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1015 "big-endian.\n",
1016 rpccli_pipe_txt(talloc_tos(), state->cli)));
1017 state->endianess = 0x00; /* BIG ENDIAN */
1020 * Check endianness on subsequent packets.
1022 if (state->endianess != state->pkt->drep[0]) {
1023 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1024 "%s\n",
1025 state->endianess?"little":"big",
1026 state->pkt->drep[0]?"little":"big"));
1028 * TODO: do a real async disconnect ...
1030 * For now do it sync...
1032 TALLOC_FREE(state->cli->transport);
1033 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1034 return;
1037 if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) {
1039 * TODO: do a real async disconnect ...
1041 * For now do it sync...
1043 TALLOC_FREE(state->cli->transport);
1044 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1045 return;
1048 /* Now copy the data portion out of the pdu into rbuf. */
1049 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
1050 if (!data_blob_realloc(NULL, &state->reply_pdu,
1051 state->reply_pdu_offset + rdata.length)) {
1053 * TODO: do a real async disconnect ...
1055 * For now do it sync...
1057 TALLOC_FREE(state->cli->transport);
1058 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1059 return;
1063 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
1064 rdata.data, rdata.length);
1065 state->reply_pdu_offset += rdata.length;
1067 /* reset state->incoming_frag, there is no need to free it,
1068 * it will be reallocated to the right size the next time
1069 * it is used */
1070 state->incoming_frag.length = 0;
1072 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1073 /* make sure the pdu length is right now that we
1074 * have all the data available (alloc hint may
1075 * have allocated more than was actually used) */
1076 state->reply_pdu.length = state->reply_pdu_offset;
1077 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1078 rpccli_pipe_txt(talloc_tos(), state->cli),
1079 (unsigned)state->reply_pdu.length));
1080 tevent_req_done(req);
1081 return;
1084 subreq = get_complete_frag_send(state, state->ev, state->cli,
1085 &state->incoming_frag);
1086 if (subreq == NULL) {
1088 * TODO: do a real async disconnect ...
1090 * For now do it sync...
1092 TALLOC_FREE(state->cli->transport);
1094 if (tevent_req_nomem(subreq, req)) {
1095 return;
1097 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1100 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1101 struct ncacn_packet **pkt,
1102 DATA_BLOB *reply_pdu)
1104 struct rpc_api_pipe_state *state = tevent_req_data(
1105 req, struct rpc_api_pipe_state);
1106 NTSTATUS status;
1108 if (tevent_req_is_nterror(req, &status)) {
1109 return status;
1112 /* return data to caller and assign it ownership of memory */
1113 if (reply_pdu) {
1114 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1115 reply_pdu->length = state->reply_pdu.length;
1116 state->reply_pdu.length = 0;
1117 } else {
1118 data_blob_free(&state->reply_pdu);
1121 if (pkt) {
1122 *pkt = talloc_steal(mem_ctx, state->pkt);
1125 return NT_STATUS_OK;
1128 /*******************************************************************
1129 Creates NTLMSSP auth bind.
1130 ********************************************************************/
1132 static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1133 TALLOC_CTX *mem_ctx,
1134 DATA_BLOB *auth_token,
1135 bool *client_hdr_signing)
1137 struct gensec_security *gensec_security;
1138 DATA_BLOB null_blob = data_blob_null;
1139 NTSTATUS status;
1141 gensec_security = cli->auth->auth_ctx;
1143 DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
1144 status = gensec_update(gensec_security, mem_ctx, null_blob, auth_token);
1146 if (!NT_STATUS_IS_OK(status) &&
1147 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1149 return status;
1152 if (client_hdr_signing == NULL) {
1153 return status;
1156 if (cli->auth->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1157 *client_hdr_signing = false;
1158 return status;
1161 *client_hdr_signing = gensec_have_feature(gensec_security,
1162 GENSEC_FEATURE_SIGN_PKT_HEADER);
1164 return status;
1167 /*******************************************************************
1168 Creates the internals of a DCE/RPC bind request or alter context PDU.
1169 ********************************************************************/
1171 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1172 enum dcerpc_pkt_type ptype,
1173 uint32_t rpc_call_id,
1174 const struct ndr_syntax_id *abstract,
1175 const struct ndr_syntax_id *transfer,
1176 const DATA_BLOB *auth_info,
1177 bool client_hdr_signing,
1178 DATA_BLOB *blob)
1180 uint16_t auth_len = auth_info->length;
1181 NTSTATUS status;
1182 union dcerpc_payload u;
1183 struct dcerpc_ctx_list ctx_list;
1184 uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1186 if (auth_len) {
1187 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1190 if (client_hdr_signing) {
1191 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1194 ctx_list.context_id = 0;
1195 ctx_list.num_transfer_syntaxes = 1;
1196 ctx_list.abstract_syntax = *abstract;
1197 ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1199 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1200 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1201 u.bind.assoc_group_id = 0x0;
1202 u.bind.num_contexts = 1;
1203 u.bind.ctx_list = &ctx_list;
1204 u.bind.auth_info = *auth_info;
1206 status = dcerpc_push_ncacn_packet(mem_ctx,
1207 ptype, pfc_flags,
1208 auth_len,
1209 rpc_call_id,
1211 blob);
1212 if (!NT_STATUS_IS_OK(status)) {
1213 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1214 return status;
1217 return NT_STATUS_OK;
1220 /*******************************************************************
1221 Creates a DCE/RPC bind request.
1222 ********************************************************************/
1224 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1225 struct rpc_pipe_client *cli,
1226 struct pipe_auth_data *auth,
1227 uint32_t rpc_call_id,
1228 const struct ndr_syntax_id *abstract,
1229 const struct ndr_syntax_id *transfer,
1230 DATA_BLOB *rpc_out)
1232 DATA_BLOB auth_token = data_blob_null;
1233 DATA_BLOB auth_info = data_blob_null;
1234 NTSTATUS ret;
1236 switch (auth->auth_type) {
1237 case DCERPC_AUTH_TYPE_NONE:
1238 break;
1240 default:
1241 ret = create_generic_auth_rpc_bind_req(cli, mem_ctx,
1242 &auth_token,
1243 &auth->client_hdr_signing);
1245 if (!NT_STATUS_IS_OK(ret) &&
1246 !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1247 return ret;
1249 break;
1252 if (auth_token.length != 0) {
1253 ret = dcerpc_push_dcerpc_auth(cli,
1254 auth->auth_type,
1255 auth->auth_level,
1256 0, /* auth_pad_length */
1257 auth->auth_context_id,
1258 &auth_token,
1259 &auth_info);
1260 if (!NT_STATUS_IS_OK(ret)) {
1261 return ret;
1263 data_blob_free(&auth_token);
1266 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1267 DCERPC_PKT_BIND,
1268 rpc_call_id,
1269 abstract,
1270 transfer,
1271 &auth_info,
1272 auth->client_hdr_signing,
1273 rpc_out);
1274 return ret;
1277 /*******************************************************************
1278 External interface.
1279 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1280 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1281 and deals with signing/sealing details.
1282 ********************************************************************/
1284 struct rpc_api_pipe_req_state {
1285 struct tevent_context *ev;
1286 struct rpc_pipe_client *cli;
1287 uint8_t op_num;
1288 uint32_t call_id;
1289 const DATA_BLOB *req_data;
1290 const struct GUID *object_uuid;
1291 uint32_t req_data_sent;
1292 DATA_BLOB req_trailer;
1293 uint32_t req_trailer_sent;
1294 bool verify_bitmask1;
1295 bool verify_pcontext;
1296 DATA_BLOB rpc_out;
1297 DATA_BLOB reply_pdu;
1300 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1301 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1302 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state);
1303 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1304 bool *is_last_frag);
1306 static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1307 struct tevent_context *ev,
1308 struct rpc_pipe_client *cli,
1309 uint8_t op_num,
1310 const struct GUID *object_uuid,
1311 const DATA_BLOB *req_data)
1313 struct tevent_req *req, *subreq;
1314 struct rpc_api_pipe_req_state *state;
1315 NTSTATUS status;
1316 bool is_last_frag;
1318 req = tevent_req_create(mem_ctx, &state,
1319 struct rpc_api_pipe_req_state);
1320 if (req == NULL) {
1321 return NULL;
1323 state->ev = ev;
1324 state->cli = cli;
1325 state->op_num = op_num;
1326 state->object_uuid = object_uuid;
1327 state->req_data = req_data;
1328 state->req_data_sent = 0;
1329 state->call_id = get_rpc_call_id();
1330 state->reply_pdu = data_blob_null;
1331 state->rpc_out = data_blob_null;
1333 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1334 + RPC_MAX_SIGN_SIZE) {
1335 /* Server is screwed up ! */
1336 status = NT_STATUS_INVALID_PARAMETER;
1337 goto post_status;
1340 status = prepare_verification_trailer(state);
1341 if (!NT_STATUS_IS_OK(status)) {
1342 goto post_status;
1345 status = prepare_next_frag(state, &is_last_frag);
1346 if (!NT_STATUS_IS_OK(status)) {
1347 goto post_status;
1350 if (is_last_frag) {
1351 subreq = rpc_api_pipe_send(state, ev, state->cli,
1352 &state->rpc_out,
1353 DCERPC_PKT_RESPONSE,
1354 state->call_id);
1355 if (subreq == NULL) {
1356 goto fail;
1358 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1359 } else {
1360 subreq = rpc_write_send(state, ev, cli->transport,
1361 state->rpc_out.data,
1362 state->rpc_out.length);
1363 if (subreq == NULL) {
1364 goto fail;
1366 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1367 req);
1369 return req;
1371 post_status:
1372 tevent_req_nterror(req, status);
1373 return tevent_req_post(req, ev);
1374 fail:
1375 TALLOC_FREE(req);
1376 return NULL;
1379 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state)
1381 struct pipe_auth_data *a = state->cli->auth;
1382 struct dcerpc_sec_verification_trailer *t;
1383 struct dcerpc_sec_vt *c = NULL;
1384 struct ndr_push *ndr = NULL;
1385 enum ndr_err_code ndr_err;
1386 size_t align = 0;
1387 size_t pad = 0;
1389 if (a == NULL) {
1390 return NT_STATUS_OK;
1393 if (a->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1394 return NT_STATUS_OK;
1397 t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1398 if (t == NULL) {
1399 return NT_STATUS_NO_MEMORY;
1402 if (!a->verified_bitmask1) {
1403 t->commands = talloc_realloc(t, t->commands,
1404 struct dcerpc_sec_vt,
1405 t->count.count + 1);
1406 if (t->commands == NULL) {
1407 return NT_STATUS_NO_MEMORY;
1409 c = &t->commands[t->count.count++];
1410 ZERO_STRUCTP(c);
1412 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1413 if (a->client_hdr_signing) {
1414 c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1416 state->verify_bitmask1 = true;
1419 if (!state->cli->verified_pcontext) {
1420 t->commands = talloc_realloc(t, t->commands,
1421 struct dcerpc_sec_vt,
1422 t->count.count + 1);
1423 if (t->commands == NULL) {
1424 return NT_STATUS_NO_MEMORY;
1426 c = &t->commands[t->count.count++];
1427 ZERO_STRUCTP(c);
1429 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1430 c->u.pcontext.abstract_syntax = state->cli->abstract_syntax;
1431 c->u.pcontext.transfer_syntax = state->cli->transfer_syntax;
1433 state->verify_pcontext = true;
1436 if (!a->hdr_signing) {
1437 t->commands = talloc_realloc(t, t->commands,
1438 struct dcerpc_sec_vt,
1439 t->count.count + 1);
1440 if (t->commands == NULL) {
1441 return NT_STATUS_NO_MEMORY;
1443 c = &t->commands[t->count.count++];
1444 ZERO_STRUCTP(c);
1446 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1447 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1448 c->u.header2.drep[0] = DCERPC_DREP_LE;
1449 c->u.header2.drep[1] = 0;
1450 c->u.header2.drep[2] = 0;
1451 c->u.header2.drep[3] = 0;
1452 c->u.header2.call_id = state->call_id;
1453 c->u.header2.context_id = 0;
1454 c->u.header2.opnum = state->op_num;
1457 if (t->count.count == 0) {
1458 TALLOC_FREE(t);
1459 return NT_STATUS_OK;
1462 c = &t->commands[t->count.count - 1];
1463 c->command |= DCERPC_SEC_VT_COMMAND_END;
1465 if (DEBUGLEVEL >= 10) {
1466 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1469 ndr = ndr_push_init_ctx(state);
1470 if (ndr == NULL) {
1471 return NT_STATUS_NO_MEMORY;
1474 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1475 NDR_SCALARS | NDR_BUFFERS,
1477 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1478 return ndr_map_error2ntstatus(ndr_err);
1480 state->req_trailer = ndr_push_blob(ndr);
1482 align = state->req_data->length & 0x3;
1483 if (align > 0) {
1484 pad = 4 - align;
1486 if (pad > 0) {
1487 bool ok;
1488 uint8_t *p;
1489 const uint8_t zeros[4] = { 0, };
1491 ok = data_blob_append(ndr, &state->req_trailer, zeros, pad);
1492 if (!ok) {
1493 return NT_STATUS_NO_MEMORY;
1496 /* move the padding to the start */
1497 p = state->req_trailer.data;
1498 memmove(p + pad, p, state->req_trailer.length - pad);
1499 memset(p, 0, pad);
1502 return NT_STATUS_OK;
1505 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1506 bool *is_last_frag)
1508 size_t auth_len;
1509 size_t frag_len;
1510 uint8_t flags = 0;
1511 size_t pad_len;
1512 size_t data_left;
1513 size_t data_thistime;
1514 size_t trailer_left;
1515 size_t trailer_thistime = 0;
1516 size_t total_left;
1517 size_t total_thistime;
1518 NTSTATUS status;
1519 bool ok;
1520 union dcerpc_payload u;
1522 data_left = state->req_data->length - state->req_data_sent;
1523 trailer_left = state->req_trailer.length - state->req_trailer_sent;
1524 total_left = data_left + trailer_left;
1525 if ((total_left < data_left) || (total_left < trailer_left)) {
1527 * overflow
1529 return NT_STATUS_INVALID_PARAMETER_MIX;
1532 status = dcerpc_guess_sizes(state->cli->auth,
1533 DCERPC_REQUEST_LENGTH, total_left,
1534 state->cli->max_xmit_frag,
1535 &total_thistime,
1536 &frag_len, &auth_len, &pad_len);
1537 if (!NT_STATUS_IS_OK(status)) {
1538 return status;
1541 if (state->req_data_sent == 0) {
1542 flags = DCERPC_PFC_FLAG_FIRST;
1545 if (total_thistime == total_left) {
1546 flags |= DCERPC_PFC_FLAG_LAST;
1549 data_thistime = MIN(total_thistime, data_left);
1550 if (data_thistime < total_thistime) {
1551 trailer_thistime = total_thistime - data_thistime;
1554 data_blob_free(&state->rpc_out);
1556 ZERO_STRUCT(u.request);
1558 u.request.alloc_hint = total_left;
1559 u.request.context_id = 0;
1560 u.request.opnum = state->op_num;
1562 if (state->object_uuid) {
1563 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1564 u.request.object.object = *state->object_uuid;
1565 frag_len += ndr_size_GUID(state->object_uuid, 0);
1568 status = dcerpc_push_ncacn_packet(state,
1569 DCERPC_PKT_REQUEST,
1570 flags,
1571 auth_len,
1572 state->call_id,
1574 &state->rpc_out);
1575 if (!NT_STATUS_IS_OK(status)) {
1576 return status;
1579 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1580 * compute it right for requests because the auth trailer is missing
1581 * at this stage */
1582 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1584 if (data_thistime > 0) {
1585 /* Copy in the data. */
1586 ok = data_blob_append(NULL, &state->rpc_out,
1587 state->req_data->data + state->req_data_sent,
1588 data_thistime);
1589 if (!ok) {
1590 return NT_STATUS_NO_MEMORY;
1592 state->req_data_sent += data_thistime;
1595 if (trailer_thistime > 0) {
1596 /* Copy in the verification trailer. */
1597 ok = data_blob_append(NULL, &state->rpc_out,
1598 state->req_trailer.data + state->req_trailer_sent,
1599 trailer_thistime);
1600 if (!ok) {
1601 return NT_STATUS_NO_MEMORY;
1603 state->req_trailer_sent += trailer_thistime;
1606 switch (state->cli->auth->auth_level) {
1607 case DCERPC_AUTH_LEVEL_NONE:
1608 case DCERPC_AUTH_LEVEL_CONNECT:
1609 break;
1610 case DCERPC_AUTH_LEVEL_PACKET:
1611 case DCERPC_AUTH_LEVEL_INTEGRITY:
1612 case DCERPC_AUTH_LEVEL_PRIVACY:
1613 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1614 &state->rpc_out);
1615 if (!NT_STATUS_IS_OK(status)) {
1616 return status;
1618 break;
1619 default:
1620 return NT_STATUS_INVALID_PARAMETER;
1623 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1625 return status;
1628 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1630 struct tevent_req *req = tevent_req_callback_data(
1631 subreq, struct tevent_req);
1632 struct rpc_api_pipe_req_state *state = tevent_req_data(
1633 req, struct rpc_api_pipe_req_state);
1634 NTSTATUS status;
1635 bool is_last_frag;
1637 status = rpc_write_recv(subreq);
1638 TALLOC_FREE(subreq);
1639 if (!NT_STATUS_IS_OK(status)) {
1640 tevent_req_nterror(req, status);
1641 return;
1644 status = prepare_next_frag(state, &is_last_frag);
1645 if (!NT_STATUS_IS_OK(status)) {
1646 tevent_req_nterror(req, status);
1647 return;
1650 if (is_last_frag) {
1651 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1652 &state->rpc_out,
1653 DCERPC_PKT_RESPONSE,
1654 state->call_id);
1655 if (tevent_req_nomem(subreq, req)) {
1656 return;
1658 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1659 } else {
1660 subreq = rpc_write_send(state, state->ev,
1661 state->cli->transport,
1662 state->rpc_out.data,
1663 state->rpc_out.length);
1664 if (tevent_req_nomem(subreq, req)) {
1665 return;
1667 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1668 req);
1672 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1674 struct tevent_req *req = tevent_req_callback_data(
1675 subreq, struct tevent_req);
1676 struct rpc_api_pipe_req_state *state = tevent_req_data(
1677 req, struct rpc_api_pipe_req_state);
1678 NTSTATUS status;
1680 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1681 TALLOC_FREE(subreq);
1682 if (!NT_STATUS_IS_OK(status)) {
1683 tevent_req_nterror(req, status);
1684 return;
1687 if (state->cli->auth == NULL) {
1688 tevent_req_done(req);
1689 return;
1692 if (state->verify_bitmask1) {
1693 state->cli->auth->verified_bitmask1 = true;
1696 if (state->verify_pcontext) {
1697 state->cli->verified_pcontext = true;
1700 tevent_req_done(req);
1703 static NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1704 DATA_BLOB *reply_pdu)
1706 struct rpc_api_pipe_req_state *state = tevent_req_data(
1707 req, struct rpc_api_pipe_req_state);
1708 NTSTATUS status;
1710 if (tevent_req_is_nterror(req, &status)) {
1712 * We always have to initialize to reply pdu, even if there is
1713 * none. The rpccli_* caller routines expect this.
1715 *reply_pdu = data_blob_null;
1716 return status;
1719 /* return data to caller and assign it ownership of memory */
1720 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1721 reply_pdu->length = state->reply_pdu.length;
1722 state->reply_pdu.length = 0;
1724 return NT_STATUS_OK;
1727 /****************************************************************************
1728 Check the rpc bind acknowledge response.
1729 ****************************************************************************/
1731 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1732 const struct ndr_syntax_id *transfer)
1734 struct dcerpc_ack_ctx ctx;
1736 if (r->secondary_address_size == 0) {
1737 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1740 if (r->num_results < 1 || !r->ctx_list) {
1741 return false;
1744 ctx = r->ctx_list[0];
1746 /* check the transfer syntax */
1747 if ((ctx.syntax.if_version != transfer->if_version) ||
1748 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1749 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1750 return False;
1753 if (r->num_results != 0x1 || ctx.result != 0) {
1754 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1755 r->num_results, ctx.reason.value));
1758 DEBUG(5,("check_bind_response: accepted!\n"));
1759 return True;
1762 /*******************************************************************
1763 Creates a DCE/RPC bind authentication response.
1764 This is the packet that is sent back to the server once we
1765 have received a BIND-ACK, to finish the third leg of
1766 the authentication handshake.
1767 ********************************************************************/
1769 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1770 struct rpc_pipe_client *cli,
1771 struct pipe_auth_data *auth,
1772 uint32_t rpc_call_id,
1773 DATA_BLOB *pauth_blob,
1774 DATA_BLOB *rpc_out)
1776 NTSTATUS status;
1777 union dcerpc_payload u;
1779 u.auth3._pad = 0;
1781 status = dcerpc_push_dcerpc_auth(mem_ctx,
1782 auth->auth_type,
1783 auth->auth_level,
1784 0, /* auth_pad_length */
1785 auth->auth_context_id,
1786 pauth_blob,
1787 &u.auth3.auth_info);
1788 if (!NT_STATUS_IS_OK(status)) {
1789 return status;
1792 status = dcerpc_push_ncacn_packet(mem_ctx,
1793 DCERPC_PKT_AUTH3,
1794 DCERPC_PFC_FLAG_FIRST |
1795 DCERPC_PFC_FLAG_LAST,
1796 pauth_blob->length,
1797 rpc_call_id,
1799 rpc_out);
1800 data_blob_free(&u.auth3.auth_info);
1801 if (!NT_STATUS_IS_OK(status)) {
1802 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1803 return status;
1806 return NT_STATUS_OK;
1809 /*******************************************************************
1810 Creates a DCE/RPC bind alter context authentication request which
1811 may contain a spnego auth blobl
1812 ********************************************************************/
1814 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1815 struct pipe_auth_data *auth,
1816 uint32_t rpc_call_id,
1817 const struct ndr_syntax_id *abstract,
1818 const struct ndr_syntax_id *transfer,
1819 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1820 DATA_BLOB *rpc_out)
1822 DATA_BLOB auth_info;
1823 NTSTATUS status;
1825 status = dcerpc_push_dcerpc_auth(mem_ctx,
1826 auth->auth_type,
1827 auth->auth_level,
1828 0, /* auth_pad_length */
1829 auth->auth_context_id,
1830 pauth_blob,
1831 &auth_info);
1832 if (!NT_STATUS_IS_OK(status)) {
1833 return status;
1836 status = create_bind_or_alt_ctx_internal(mem_ctx,
1837 DCERPC_PKT_ALTER,
1838 rpc_call_id,
1839 abstract,
1840 transfer,
1841 &auth_info,
1842 false, /* client_hdr_signing */
1843 rpc_out);
1844 data_blob_free(&auth_info);
1845 return status;
1848 /****************************************************************************
1849 Do an rpc bind.
1850 ****************************************************************************/
1852 struct rpc_pipe_bind_state {
1853 struct tevent_context *ev;
1854 struct rpc_pipe_client *cli;
1855 DATA_BLOB rpc_out;
1856 bool auth3;
1857 uint32_t rpc_call_id;
1860 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1861 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1862 struct rpc_pipe_bind_state *state,
1863 DATA_BLOB *credentials);
1864 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1865 struct rpc_pipe_bind_state *state,
1866 DATA_BLOB *credentials);
1868 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1869 struct tevent_context *ev,
1870 struct rpc_pipe_client *cli,
1871 struct pipe_auth_data *auth)
1873 struct tevent_req *req, *subreq;
1874 struct rpc_pipe_bind_state *state;
1875 NTSTATUS status;
1877 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1878 if (req == NULL) {
1879 return NULL;
1882 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1883 rpccli_pipe_txt(talloc_tos(), cli),
1884 (unsigned int)auth->auth_type,
1885 (unsigned int)auth->auth_level ));
1887 state->ev = ev;
1888 state->cli = cli;
1889 state->rpc_call_id = get_rpc_call_id();
1891 cli->auth = talloc_move(cli, &auth);
1893 /* Marshall the outgoing data. */
1894 status = create_rpc_bind_req(state, cli,
1895 cli->auth,
1896 state->rpc_call_id,
1897 &cli->abstract_syntax,
1898 &cli->transfer_syntax,
1899 &state->rpc_out);
1901 if (!NT_STATUS_IS_OK(status) &&
1902 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1903 goto post_status;
1906 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1907 DCERPC_PKT_BIND_ACK, state->rpc_call_id);
1908 if (subreq == NULL) {
1909 goto fail;
1911 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1912 return req;
1914 post_status:
1915 tevent_req_nterror(req, status);
1916 return tevent_req_post(req, ev);
1917 fail:
1918 TALLOC_FREE(req);
1919 return NULL;
1922 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1924 struct tevent_req *req = tevent_req_callback_data(
1925 subreq, struct tevent_req);
1926 struct rpc_pipe_bind_state *state = tevent_req_data(
1927 req, struct rpc_pipe_bind_state);
1928 struct pipe_auth_data *pauth = state->cli->auth;
1929 struct gensec_security *gensec_security;
1930 struct ncacn_packet *pkt = NULL;
1931 struct dcerpc_auth auth;
1932 DATA_BLOB auth_token = data_blob_null;
1933 NTSTATUS status;
1935 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
1936 TALLOC_FREE(subreq);
1937 if (!NT_STATUS_IS_OK(status)) {
1938 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1939 rpccli_pipe_txt(talloc_tos(), state->cli),
1940 nt_errstr(status)));
1941 tevent_req_nterror(req, status);
1942 return;
1945 if (state->auth3) {
1946 tevent_req_done(req);
1947 return;
1950 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1951 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1952 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1953 return;
1956 if (pkt->ptype == DCERPC_PKT_BIND_ACK) {
1957 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1958 if (pauth->client_hdr_signing) {
1959 pauth->hdr_signing = true;
1964 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1966 switch(pauth->auth_type) {
1968 case DCERPC_AUTH_TYPE_NONE:
1969 /* Bind complete. */
1970 tevent_req_done(req);
1971 return;
1973 default:
1974 if (pkt->auth_length == 0) {
1975 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1976 return;
1979 /* get auth credentials */
1980 status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
1981 &pkt->u.bind_ack.auth_info,
1982 &auth, NULL, true);
1983 if (!NT_STATUS_IS_OK(status)) {
1984 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1985 nt_errstr(status)));
1986 tevent_req_nterror(req, status);
1987 return;
1990 if (auth.auth_type != pauth->auth_type) {
1991 DEBUG(0, (__location__ " Auth type %u mismatch expected %u.\n",
1992 auth.auth_type, pauth->auth_type));
1993 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1994 return;
1997 if (auth.auth_level != pauth->auth_level) {
1998 DEBUG(0, (__location__ " Auth level %u mismatch expected %u.\n",
1999 auth.auth_level, pauth->auth_level));
2000 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
2001 return;
2004 if (auth.auth_context_id != pauth->auth_context_id) {
2005 DEBUG(0, (__location__ " Auth context id %u mismatch expected %u.\n",
2006 (unsigned)auth.auth_context_id,
2007 (unsigned)pauth->auth_context_id));
2008 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
2009 return;
2012 break;
2016 * For authenticated binds we may need to do 3 or 4 leg binds.
2019 switch(pauth->auth_type) {
2021 case DCERPC_AUTH_TYPE_NONE:
2022 /* Bind complete. */
2023 tevent_req_done(req);
2024 return;
2026 default:
2027 gensec_security = pauth->auth_ctx;
2030 status = gensec_update(gensec_security, state,
2031 auth.credentials, &auth_token);
2032 if (NT_STATUS_EQUAL(status,
2033 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2034 status = rpc_bind_next_send(req, state,
2035 &auth_token);
2036 } else if (NT_STATUS_IS_OK(status)) {
2037 if (pauth->hdr_signing) {
2038 gensec_want_feature(gensec_security,
2039 GENSEC_FEATURE_SIGN_PKT_HEADER);
2042 if (auth_token.length == 0) {
2043 /* Bind complete. */
2044 tevent_req_done(req);
2045 return;
2047 status = rpc_bind_finish_send(req, state,
2048 &auth_token);
2050 break;
2053 if (!NT_STATUS_IS_OK(status)) {
2054 tevent_req_nterror(req, status);
2056 return;
2059 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
2060 struct rpc_pipe_bind_state *state,
2061 DATA_BLOB *auth_token)
2063 struct pipe_auth_data *auth = state->cli->auth;
2064 struct tevent_req *subreq;
2065 NTSTATUS status;
2067 /* Now prepare the alter context pdu. */
2068 data_blob_free(&state->rpc_out);
2070 status = create_rpc_alter_context(state, auth,
2071 state->rpc_call_id,
2072 &state->cli->abstract_syntax,
2073 &state->cli->transfer_syntax,
2074 auth_token,
2075 &state->rpc_out);
2076 if (!NT_STATUS_IS_OK(status)) {
2077 return status;
2080 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2081 &state->rpc_out, DCERPC_PKT_ALTER_RESP,
2082 state->rpc_call_id);
2083 if (subreq == NULL) {
2084 return NT_STATUS_NO_MEMORY;
2086 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2087 return NT_STATUS_OK;
2090 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
2091 struct rpc_pipe_bind_state *state,
2092 DATA_BLOB *auth_token)
2094 struct pipe_auth_data *auth = state->cli->auth;
2095 struct tevent_req *subreq;
2096 NTSTATUS status;
2098 state->auth3 = true;
2100 /* Now prepare the auth3 context pdu. */
2101 data_blob_free(&state->rpc_out);
2103 status = create_rpc_bind_auth3(state, state->cli, auth,
2104 state->rpc_call_id,
2105 auth_token,
2106 &state->rpc_out);
2107 if (!NT_STATUS_IS_OK(status)) {
2108 return status;
2111 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2112 &state->rpc_out, DCERPC_PKT_AUTH3,
2113 state->rpc_call_id);
2114 if (subreq == NULL) {
2115 return NT_STATUS_NO_MEMORY;
2117 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2118 return NT_STATUS_OK;
2121 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2123 return tevent_req_simple_recv_ntstatus(req);
2126 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2127 struct pipe_auth_data *auth)
2129 TALLOC_CTX *frame = talloc_stackframe();
2130 struct tevent_context *ev;
2131 struct tevent_req *req;
2132 NTSTATUS status = NT_STATUS_OK;
2134 ev = samba_tevent_context_init(frame);
2135 if (ev == NULL) {
2136 status = NT_STATUS_NO_MEMORY;
2137 goto fail;
2140 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2141 if (req == NULL) {
2142 status = NT_STATUS_NO_MEMORY;
2143 goto fail;
2146 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2147 goto fail;
2150 status = rpc_pipe_bind_recv(req);
2151 fail:
2152 TALLOC_FREE(frame);
2153 return status;
2156 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2158 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2159 unsigned int timeout)
2161 unsigned int old;
2163 if (rpc_cli->transport == NULL) {
2164 return RPCCLI_DEFAULT_TIMEOUT;
2167 if (rpc_cli->transport->set_timeout == NULL) {
2168 return RPCCLI_DEFAULT_TIMEOUT;
2171 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2172 if (old == 0) {
2173 return RPCCLI_DEFAULT_TIMEOUT;
2176 return old;
2179 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2181 if (rpc_cli == NULL) {
2182 return false;
2185 if (rpc_cli->transport == NULL) {
2186 return false;
2189 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2192 struct rpccli_bh_state {
2193 struct rpc_pipe_client *rpc_cli;
2196 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2198 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2199 struct rpccli_bh_state);
2201 return rpccli_is_connected(hs->rpc_cli);
2204 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2205 uint32_t timeout)
2207 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2208 struct rpccli_bh_state);
2210 return rpccli_set_timeout(hs->rpc_cli, timeout);
2213 static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
2214 enum dcerpc_AuthType *auth_type,
2215 enum dcerpc_AuthLevel *auth_level)
2217 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2218 struct rpccli_bh_state);
2220 if (hs->rpc_cli == NULL) {
2221 return;
2224 if (hs->rpc_cli->auth == NULL) {
2225 return;
2228 *auth_type = hs->rpc_cli->auth->auth_type;
2229 *auth_level = hs->rpc_cli->auth->auth_level;
2232 struct rpccli_bh_raw_call_state {
2233 DATA_BLOB in_data;
2234 DATA_BLOB out_data;
2235 uint32_t out_flags;
2238 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2240 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2241 struct tevent_context *ev,
2242 struct dcerpc_binding_handle *h,
2243 const struct GUID *object,
2244 uint32_t opnum,
2245 uint32_t in_flags,
2246 const uint8_t *in_data,
2247 size_t in_length)
2249 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2250 struct rpccli_bh_state);
2251 struct tevent_req *req;
2252 struct rpccli_bh_raw_call_state *state;
2253 bool ok;
2254 struct tevent_req *subreq;
2256 req = tevent_req_create(mem_ctx, &state,
2257 struct rpccli_bh_raw_call_state);
2258 if (req == NULL) {
2259 return NULL;
2261 state->in_data.data = discard_const_p(uint8_t, in_data);
2262 state->in_data.length = in_length;
2264 ok = rpccli_bh_is_connected(h);
2265 if (!ok) {
2266 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2267 return tevent_req_post(req, ev);
2270 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2271 opnum, object, &state->in_data);
2272 if (tevent_req_nomem(subreq, req)) {
2273 return tevent_req_post(req, ev);
2275 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2277 return req;
2280 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2282 struct tevent_req *req =
2283 tevent_req_callback_data(subreq,
2284 struct tevent_req);
2285 struct rpccli_bh_raw_call_state *state =
2286 tevent_req_data(req,
2287 struct rpccli_bh_raw_call_state);
2288 NTSTATUS status;
2290 state->out_flags = 0;
2292 /* TODO: support bigendian responses */
2294 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2295 TALLOC_FREE(subreq);
2296 if (!NT_STATUS_IS_OK(status)) {
2297 tevent_req_nterror(req, status);
2298 return;
2301 tevent_req_done(req);
2304 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2305 TALLOC_CTX *mem_ctx,
2306 uint8_t **out_data,
2307 size_t *out_length,
2308 uint32_t *out_flags)
2310 struct rpccli_bh_raw_call_state *state =
2311 tevent_req_data(req,
2312 struct rpccli_bh_raw_call_state);
2313 NTSTATUS status;
2315 if (tevent_req_is_nterror(req, &status)) {
2316 tevent_req_received(req);
2317 return status;
2320 *out_data = talloc_move(mem_ctx, &state->out_data.data);
2321 *out_length = state->out_data.length;
2322 *out_flags = state->out_flags;
2323 tevent_req_received(req);
2324 return NT_STATUS_OK;
2327 struct rpccli_bh_disconnect_state {
2328 uint8_t _dummy;
2331 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2332 struct tevent_context *ev,
2333 struct dcerpc_binding_handle *h)
2335 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2336 struct rpccli_bh_state);
2337 struct tevent_req *req;
2338 struct rpccli_bh_disconnect_state *state;
2339 bool ok;
2341 req = tevent_req_create(mem_ctx, &state,
2342 struct rpccli_bh_disconnect_state);
2343 if (req == NULL) {
2344 return NULL;
2347 ok = rpccli_bh_is_connected(h);
2348 if (!ok) {
2349 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2350 return tevent_req_post(req, ev);
2354 * TODO: do a real async disconnect ...
2356 * For now we do it sync...
2358 TALLOC_FREE(hs->rpc_cli->transport);
2359 hs->rpc_cli = NULL;
2361 tevent_req_done(req);
2362 return tevent_req_post(req, ev);
2365 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2367 NTSTATUS status;
2369 if (tevent_req_is_nterror(req, &status)) {
2370 tevent_req_received(req);
2371 return status;
2374 tevent_req_received(req);
2375 return NT_STATUS_OK;
2378 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2380 return true;
2383 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2384 int ndr_flags,
2385 const void *_struct_ptr,
2386 const struct ndr_interface_call *call)
2388 void *struct_ptr = discard_const(_struct_ptr);
2390 if (DEBUGLEVEL < 10) {
2391 return;
2394 if (ndr_flags & NDR_IN) {
2395 ndr_print_function_debug(call->ndr_print,
2396 call->name,
2397 ndr_flags,
2398 struct_ptr);
2400 if (ndr_flags & NDR_OUT) {
2401 ndr_print_function_debug(call->ndr_print,
2402 call->name,
2403 ndr_flags,
2404 struct_ptr);
2408 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2409 .name = "rpccli",
2410 .is_connected = rpccli_bh_is_connected,
2411 .set_timeout = rpccli_bh_set_timeout,
2412 .auth_info = rpccli_bh_auth_info,
2413 .raw_call_send = rpccli_bh_raw_call_send,
2414 .raw_call_recv = rpccli_bh_raw_call_recv,
2415 .disconnect_send = rpccli_bh_disconnect_send,
2416 .disconnect_recv = rpccli_bh_disconnect_recv,
2418 .ref_alloc = rpccli_bh_ref_alloc,
2419 .do_ndr_print = rpccli_bh_do_ndr_print,
2422 /* initialise a rpc_pipe_client binding handle */
2423 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2424 const struct GUID *object,
2425 const struct ndr_interface_table *table)
2427 struct dcerpc_binding_handle *h;
2428 struct rpccli_bh_state *hs;
2430 h = dcerpc_binding_handle_create(c,
2431 &rpccli_bh_ops,
2432 object,
2433 table,
2434 &hs,
2435 struct rpccli_bh_state,
2436 __location__);
2437 if (h == NULL) {
2438 return NULL;
2440 hs->rpc_cli = c;
2442 return h;
2445 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2446 struct pipe_auth_data **presult)
2448 struct pipe_auth_data *result;
2449 struct auth_generic_state *auth_generic_ctx;
2450 NTSTATUS status;
2452 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2453 if (result == NULL) {
2454 return NT_STATUS_NO_MEMORY;
2457 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2458 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2459 result->auth_context_id = 0;
2461 status = auth_generic_client_prepare(result,
2462 &auth_generic_ctx);
2463 if (!NT_STATUS_IS_OK(status)) {
2464 DEBUG(1, ("Failed to create auth_generic context: %s\n",
2465 nt_errstr(status)));
2468 status = auth_generic_set_username(auth_generic_ctx, "");
2469 if (!NT_STATUS_IS_OK(status)) {
2470 DEBUG(1, ("Failed to set username: %s\n",
2471 nt_errstr(status)));
2474 status = auth_generic_set_domain(auth_generic_ctx, "");
2475 if (!NT_STATUS_IS_OK(status)) {
2476 DEBUG(1, ("Failed to set domain: %s\n",
2477 nt_errstr(status)));
2478 return status;
2481 status = gensec_set_credentials(auth_generic_ctx->gensec_security,
2482 auth_generic_ctx->credentials);
2483 if (!NT_STATUS_IS_OK(status)) {
2484 DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
2485 nt_errstr(status)));
2486 return status;
2488 talloc_unlink(auth_generic_ctx, auth_generic_ctx->credentials);
2489 auth_generic_ctx->credentials = NULL;
2491 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2492 talloc_free(auth_generic_ctx);
2493 *presult = result;
2494 return NT_STATUS_OK;
2497 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2498 enum dcerpc_AuthType auth_type,
2499 enum dcerpc_AuthLevel auth_level,
2500 const char *server,
2501 const char *target_service,
2502 const char *domain,
2503 const char *username,
2504 const char *password,
2505 enum credentials_use_kerberos use_kerberos,
2506 struct netlogon_creds_CredentialState *creds,
2507 struct pipe_auth_data **presult)
2509 struct auth_generic_state *auth_generic_ctx;
2510 struct pipe_auth_data *result;
2511 NTSTATUS status;
2513 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2514 if (result == NULL) {
2515 return NT_STATUS_NO_MEMORY;
2518 result->auth_type = auth_type;
2519 result->auth_level = auth_level;
2520 result->auth_context_id = 1;
2522 status = auth_generic_client_prepare(result,
2523 &auth_generic_ctx);
2524 if (!NT_STATUS_IS_OK(status)) {
2525 goto fail;
2528 status = auth_generic_set_username(auth_generic_ctx, username);
2529 if (!NT_STATUS_IS_OK(status)) {
2530 goto fail;
2533 status = auth_generic_set_domain(auth_generic_ctx, domain);
2534 if (!NT_STATUS_IS_OK(status)) {
2535 goto fail;
2538 status = auth_generic_set_password(auth_generic_ctx, password);
2539 if (!NT_STATUS_IS_OK(status)) {
2540 goto fail;
2543 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2544 if (!NT_STATUS_IS_OK(status)) {
2545 goto fail;
2548 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2549 if (!NT_STATUS_IS_OK(status)) {
2550 goto fail;
2553 cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos);
2554 cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
2556 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2557 if (!NT_STATUS_IS_OK(status)) {
2558 goto fail;
2561 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2562 talloc_free(auth_generic_ctx);
2563 *presult = result;
2564 return NT_STATUS_OK;
2566 fail:
2567 TALLOC_FREE(result);
2568 return status;
2571 /* This routine steals the creds pointer that is passed in */
2572 static NTSTATUS rpccli_generic_bind_data_from_creds(TALLOC_CTX *mem_ctx,
2573 enum dcerpc_AuthType auth_type,
2574 enum dcerpc_AuthLevel auth_level,
2575 const char *server,
2576 const char *target_service,
2577 struct cli_credentials *creds,
2578 struct pipe_auth_data **presult)
2580 struct auth_generic_state *auth_generic_ctx;
2581 struct pipe_auth_data *result;
2582 NTSTATUS status;
2584 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2585 if (result == NULL) {
2586 return NT_STATUS_NO_MEMORY;
2589 result->auth_type = auth_type;
2590 result->auth_level = auth_level;
2591 result->auth_context_id = 1;
2593 status = auth_generic_client_prepare(result,
2594 &auth_generic_ctx);
2595 if (!NT_STATUS_IS_OK(status)) {
2596 goto fail;
2599 status = auth_generic_set_creds(auth_generic_ctx, creds);
2600 if (!NT_STATUS_IS_OK(status)) {
2601 goto fail;
2604 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2605 if (!NT_STATUS_IS_OK(status)) {
2606 goto fail;
2609 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2610 if (!NT_STATUS_IS_OK(status)) {
2611 goto fail;
2614 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2615 if (!NT_STATUS_IS_OK(status)) {
2616 goto fail;
2619 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2620 talloc_free(auth_generic_ctx);
2621 *presult = result;
2622 return NT_STATUS_OK;
2624 fail:
2625 TALLOC_FREE(result);
2626 return status;
2629 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2630 struct pipe_auth_data **presult)
2632 return rpccli_generic_bind_data(mem_ctx,
2633 DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
2634 DCERPC_AUTH_LEVEL_CONNECT,
2635 NULL, /* server */
2636 "host", /* target_service */
2637 NAME_NT_AUTHORITY, /* domain */
2638 "SYSTEM",
2639 NULL, /* password */
2640 CRED_DONT_USE_KERBEROS,
2641 NULL, /* netlogon_creds_CredentialState */
2642 presult);
2646 * Create an rpc pipe client struct, connecting to a tcp port.
2648 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2649 const struct sockaddr_storage *ss_addr,
2650 uint16_t port,
2651 const struct ndr_interface_table *table,
2652 struct rpc_pipe_client **presult)
2654 struct rpc_pipe_client *result;
2655 struct sockaddr_storage addr;
2656 NTSTATUS status;
2657 int fd;
2659 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2660 if (result == NULL) {
2661 return NT_STATUS_NO_MEMORY;
2664 result->abstract_syntax = table->syntax_id;
2665 result->transfer_syntax = ndr_transfer_syntax_ndr;
2667 result->desthost = talloc_strdup(result, host);
2668 if (result->desthost == NULL) {
2669 status = NT_STATUS_NO_MEMORY;
2670 goto fail;
2673 result->srv_name_slash = talloc_asprintf_strupper_m(
2674 result, "\\\\%s", result->desthost);
2675 if (result->srv_name_slash == NULL) {
2676 status = NT_STATUS_NO_MEMORY;
2677 goto fail;
2680 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2682 if (ss_addr == NULL) {
2683 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2684 status = NT_STATUS_NOT_FOUND;
2685 goto fail;
2687 } else {
2688 addr = *ss_addr;
2691 status = open_socket_out(&addr, port, 60*1000, &fd);
2692 if (!NT_STATUS_IS_OK(status)) {
2693 goto fail;
2695 set_socket_options(fd, lp_socket_options());
2697 status = rpc_transport_sock_init(result, fd, &result->transport);
2698 if (!NT_STATUS_IS_OK(status)) {
2699 close(fd);
2700 goto fail;
2703 result->transport->transport = NCACN_IP_TCP;
2705 result->binding_handle = rpccli_bh_create(result, NULL, table);
2706 if (result->binding_handle == NULL) {
2707 TALLOC_FREE(result);
2708 return NT_STATUS_NO_MEMORY;
2711 *presult = result;
2712 return NT_STATUS_OK;
2714 fail:
2715 TALLOC_FREE(result);
2716 return status;
2720 * Determine the tcp port on which a dcerpc interface is listening
2721 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2722 * target host.
2724 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2725 const struct sockaddr_storage *addr,
2726 const struct ndr_interface_table *table,
2727 uint16_t *pport)
2729 NTSTATUS status;
2730 struct rpc_pipe_client *epm_pipe = NULL;
2731 struct dcerpc_binding_handle *epm_handle = NULL;
2732 struct pipe_auth_data *auth = NULL;
2733 struct dcerpc_binding *map_binding = NULL;
2734 struct dcerpc_binding *res_binding = NULL;
2735 enum dcerpc_transport_t transport;
2736 const char *endpoint = NULL;
2737 struct epm_twr_t *map_tower = NULL;
2738 struct epm_twr_t *res_towers = NULL;
2739 struct policy_handle *entry_handle = NULL;
2740 uint32_t num_towers = 0;
2741 uint32_t max_towers = 1;
2742 struct epm_twr_p_t towers;
2743 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2744 uint32_t result = 0;
2746 if (pport == NULL) {
2747 status = NT_STATUS_INVALID_PARAMETER;
2748 goto done;
2751 if (ndr_syntax_id_equal(&table->syntax_id,
2752 &ndr_table_epmapper.syntax_id)) {
2753 *pport = 135;
2754 status = NT_STATUS_OK;
2755 goto done;
2758 /* open the connection to the endpoint mapper */
2759 status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2760 &ndr_table_epmapper,
2761 &epm_pipe);
2763 if (!NT_STATUS_IS_OK(status)) {
2764 goto done;
2766 epm_handle = epm_pipe->binding_handle;
2768 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2769 if (!NT_STATUS_IS_OK(status)) {
2770 goto done;
2773 status = rpc_pipe_bind(epm_pipe, auth);
2774 if (!NT_STATUS_IS_OK(status)) {
2775 goto done;
2778 /* create tower for asking the epmapper */
2780 status = dcerpc_parse_binding(tmp_ctx, "ncacn_ip_tcp:[135]",
2781 &map_binding);
2782 if (!NT_STATUS_IS_OK(status)) {
2783 goto done;
2786 status = dcerpc_binding_set_abstract_syntax(map_binding,
2787 &table->syntax_id);
2788 if (!NT_STATUS_IS_OK(status)) {
2789 goto done;
2792 map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
2793 if (map_tower == NULL) {
2794 status = NT_STATUS_NO_MEMORY;
2795 goto done;
2798 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2799 &(map_tower->tower));
2800 if (!NT_STATUS_IS_OK(status)) {
2801 goto done;
2804 /* allocate further parameters for the epm_Map call */
2806 res_towers = talloc_array(tmp_ctx, struct epm_twr_t, max_towers);
2807 if (res_towers == NULL) {
2808 status = NT_STATUS_NO_MEMORY;
2809 goto done;
2811 towers.twr = res_towers;
2813 entry_handle = talloc_zero(tmp_ctx, struct policy_handle);
2814 if (entry_handle == NULL) {
2815 status = NT_STATUS_NO_MEMORY;
2816 goto done;
2819 /* ask the endpoint mapper for the port */
2821 status = dcerpc_epm_Map(epm_handle,
2822 tmp_ctx,
2823 discard_const_p(struct GUID,
2824 &(table->syntax_id.uuid)),
2825 map_tower,
2826 entry_handle,
2827 max_towers,
2828 &num_towers,
2829 &towers,
2830 &result);
2832 if (!NT_STATUS_IS_OK(status)) {
2833 goto done;
2836 if (result != EPMAPPER_STATUS_OK) {
2837 status = NT_STATUS_UNSUCCESSFUL;
2838 goto done;
2841 if (num_towers != 1) {
2842 status = NT_STATUS_UNSUCCESSFUL;
2843 goto done;
2846 /* extract the port from the answer */
2848 status = dcerpc_binding_from_tower(tmp_ctx,
2849 &(towers.twr->tower),
2850 &res_binding);
2851 if (!NT_STATUS_IS_OK(status)) {
2852 goto done;
2855 transport = dcerpc_binding_get_transport(res_binding);
2856 endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
2858 /* are further checks here necessary? */
2859 if (transport != NCACN_IP_TCP) {
2860 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2861 goto done;
2864 if (endpoint == NULL) {
2865 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2866 goto done;
2869 *pport = (uint16_t)atoi(endpoint);
2871 done:
2872 TALLOC_FREE(tmp_ctx);
2873 return status;
2877 * Create a rpc pipe client struct, connecting to a host via tcp.
2878 * The port is determined by asking the endpoint mapper on the given
2879 * host.
2881 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2882 const struct sockaddr_storage *addr,
2883 const struct ndr_interface_table *table,
2884 struct rpc_pipe_client **presult)
2886 NTSTATUS status;
2887 uint16_t port = 0;
2889 status = rpc_pipe_get_tcp_port(host, addr, table, &port);
2890 if (!NT_STATUS_IS_OK(status)) {
2891 return status;
2894 return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2895 table, presult);
2898 /********************************************************************
2899 Create a rpc pipe client struct, connecting to a unix domain socket
2900 ********************************************************************/
2901 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2902 const struct ndr_interface_table *table,
2903 struct rpc_pipe_client **presult)
2905 struct rpc_pipe_client *result;
2906 struct sockaddr_un addr;
2907 NTSTATUS status;
2908 int fd;
2909 socklen_t salen;
2911 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2912 if (result == NULL) {
2913 return NT_STATUS_NO_MEMORY;
2916 result->abstract_syntax = table->syntax_id;
2917 result->transfer_syntax = ndr_transfer_syntax_ndr;
2919 result->desthost = get_myname(result);
2920 if (result->desthost == NULL) {
2921 status = NT_STATUS_NO_MEMORY;
2922 goto fail;
2925 result->srv_name_slash = talloc_asprintf_strupper_m(
2926 result, "\\\\%s", result->desthost);
2927 if (result->srv_name_slash == NULL) {
2928 status = NT_STATUS_NO_MEMORY;
2929 goto fail;
2932 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2934 fd = socket(AF_UNIX, SOCK_STREAM, 0);
2935 if (fd == -1) {
2936 status = map_nt_error_from_unix(errno);
2937 goto fail;
2940 ZERO_STRUCT(addr);
2941 addr.sun_family = AF_UNIX;
2942 strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2943 salen = sizeof(struct sockaddr_un);
2945 if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
2946 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2947 strerror(errno)));
2948 close(fd);
2949 return map_nt_error_from_unix(errno);
2952 status = rpc_transport_sock_init(result, fd, &result->transport);
2953 if (!NT_STATUS_IS_OK(status)) {
2954 close(fd);
2955 goto fail;
2958 result->transport->transport = NCALRPC;
2960 result->binding_handle = rpccli_bh_create(result, NULL, table);
2961 if (result->binding_handle == NULL) {
2962 TALLOC_FREE(result);
2963 return NT_STATUS_NO_MEMORY;
2966 *presult = result;
2967 return NT_STATUS_OK;
2969 fail:
2970 TALLOC_FREE(result);
2971 return status;
2974 struct rpc_pipe_client_np_ref {
2975 struct cli_state *cli;
2976 struct rpc_pipe_client *pipe;
2979 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2981 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2982 return 0;
2985 /****************************************************************************
2986 Open a named pipe over SMB to a remote server.
2988 * CAVEAT CALLER OF THIS FUNCTION:
2989 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2990 * so be sure that this function is called AFTER any structure (vs pointer)
2991 * assignment of the cli. In particular, libsmbclient does structure
2992 * assignments of cli, which invalidates the data in the returned
2993 * rpc_pipe_client if this function is called before the structure assignment
2994 * of cli.
2996 ****************************************************************************/
2998 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2999 const struct ndr_interface_table *table,
3000 struct rpc_pipe_client **presult)
3002 struct rpc_pipe_client *result;
3003 NTSTATUS status;
3004 struct rpc_pipe_client_np_ref *np_ref;
3006 /* sanity check to protect against crashes */
3008 if ( !cli ) {
3009 return NT_STATUS_INVALID_HANDLE;
3012 result = talloc_zero(NULL, struct rpc_pipe_client);
3013 if (result == NULL) {
3014 return NT_STATUS_NO_MEMORY;
3017 result->abstract_syntax = table->syntax_id;
3018 result->transfer_syntax = ndr_transfer_syntax_ndr;
3020 result->desthost = talloc_strdup(
3021 result, smbXcli_conn_remote_name(cli->conn));
3022 if (result->desthost == NULL) {
3023 TALLOC_FREE(result);
3024 return NT_STATUS_NO_MEMORY;
3027 result->srv_name_slash = talloc_asprintf_strupper_m(
3028 result, "\\\\%s", result->desthost);
3029 if (result->srv_name_slash == NULL) {
3030 TALLOC_FREE(result);
3031 return NT_STATUS_NO_MEMORY;
3034 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3036 status = rpc_transport_np_init(result, cli, table,
3037 &result->transport);
3038 if (!NT_STATUS_IS_OK(status)) {
3039 TALLOC_FREE(result);
3040 return status;
3043 result->transport->transport = NCACN_NP;
3045 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3046 if (np_ref == NULL) {
3047 TALLOC_FREE(result);
3048 return NT_STATUS_NO_MEMORY;
3050 np_ref->cli = cli;
3051 np_ref->pipe = result;
3053 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3054 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3056 result->binding_handle = rpccli_bh_create(result, NULL, table);
3057 if (result->binding_handle == NULL) {
3058 TALLOC_FREE(result);
3059 return NT_STATUS_NO_MEMORY;
3062 *presult = result;
3063 return NT_STATUS_OK;
3066 /****************************************************************************
3067 Open a pipe to a remote server.
3068 ****************************************************************************/
3070 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3071 enum dcerpc_transport_t transport,
3072 const struct ndr_interface_table *table,
3073 struct rpc_pipe_client **presult)
3075 switch (transport) {
3076 case NCACN_IP_TCP:
3077 return rpc_pipe_open_tcp(NULL,
3078 smbXcli_conn_remote_name(cli->conn),
3079 smbXcli_conn_remote_sockaddr(cli->conn),
3080 table, presult);
3081 case NCACN_NP:
3082 return rpc_pipe_open_np(cli, table, presult);
3083 default:
3084 return NT_STATUS_NOT_IMPLEMENTED;
3088 /****************************************************************************
3089 Open a named pipe to an SMB server and bind anonymously.
3090 ****************************************************************************/
3092 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3093 enum dcerpc_transport_t transport,
3094 const struct ndr_interface_table *table,
3095 struct rpc_pipe_client **presult)
3097 struct rpc_pipe_client *result;
3098 struct pipe_auth_data *auth;
3099 NTSTATUS status;
3101 status = cli_rpc_pipe_open(cli, transport, table, &result);
3102 if (!NT_STATUS_IS_OK(status)) {
3103 return status;
3106 status = rpccli_anon_bind_data(result, &auth);
3107 if (!NT_STATUS_IS_OK(status)) {
3108 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3109 nt_errstr(status)));
3110 TALLOC_FREE(result);
3111 return status;
3115 * This is a bit of an abstraction violation due to the fact that an
3116 * anonymous bind on an authenticated SMB inherits the user/domain
3117 * from the enclosing SMB creds
3120 if (transport == NCACN_NP) {
3121 struct smbXcli_session *session;
3123 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3124 session = cli->smb2.session;
3125 } else {
3126 session = cli->smb1.session;
3129 status = smbXcli_session_application_key(session, auth,
3130 &auth->transport_session_key);
3131 if (!NT_STATUS_IS_OK(status)) {
3132 auth->transport_session_key = data_blob_null;
3136 status = rpc_pipe_bind(result, auth);
3137 if (!NT_STATUS_IS_OK(status)) {
3138 int lvl = 0;
3139 if (ndr_syntax_id_equal(&table->syntax_id,
3140 &ndr_table_dssetup.syntax_id)) {
3141 /* non AD domains just don't have this pipe, avoid
3142 * level 0 statement in that case - gd */
3143 lvl = 3;
3145 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3146 "%s failed with error %s\n",
3147 table->name,
3148 nt_errstr(status) ));
3149 TALLOC_FREE(result);
3150 return status;
3153 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3154 "%s and bound anonymously.\n",
3155 table->name,
3156 result->desthost));
3158 *presult = result;
3159 return NT_STATUS_OK;
3162 /****************************************************************************
3163 ****************************************************************************/
3165 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3166 const struct ndr_interface_table *table,
3167 struct rpc_pipe_client **presult)
3169 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3170 table, presult);
3173 /****************************************************************************
3174 Open a named pipe to an SMB server and bind using the mech specified
3176 This routine references the creds pointer that is passed in
3177 ****************************************************************************/
3179 NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
3180 const struct ndr_interface_table *table,
3181 enum dcerpc_transport_t transport,
3182 enum dcerpc_AuthType auth_type,
3183 enum dcerpc_AuthLevel auth_level,
3184 const char *server,
3185 struct cli_credentials *creds,
3186 struct rpc_pipe_client **presult)
3188 struct rpc_pipe_client *result;
3189 struct pipe_auth_data *auth = NULL;
3190 const char *target_service = table->authservices->names[0];
3191 NTSTATUS status;
3193 status = cli_rpc_pipe_open(cli, transport, table, &result);
3194 if (!NT_STATUS_IS_OK(status)) {
3195 return status;
3198 status = rpccli_generic_bind_data_from_creds(result,
3199 auth_type, auth_level,
3200 server, target_service,
3201 creds,
3202 &auth);
3203 if (!NT_STATUS_IS_OK(status)) {
3204 DBG_ERR("rpccli_generic_bind_data_from_creds returned %s\n",
3205 nt_errstr(status));
3206 goto err;
3209 status = rpc_pipe_bind(result, auth);
3210 if (!NT_STATUS_IS_OK(status)) {
3211 DBG_ERR("cli_rpc_pipe_bind failed with error %s\n",
3212 nt_errstr(status));
3213 goto err;
3216 DBG_DEBUG("opened pipe %s to machine %s and bound as user %s.\n",
3217 table->name,
3218 result->desthost,
3219 cli_credentials_get_unparsed_name(creds, talloc_tos()));
3221 *presult = result;
3222 return NT_STATUS_OK;
3224 err:
3226 TALLOC_FREE(result);
3227 return status;
3230 NTSTATUS cli_rpc_pipe_open_bind_schannel(
3231 struct cli_state *cli,
3232 const struct ndr_interface_table *table,
3233 enum dcerpc_transport_t transport,
3234 struct netlogon_creds_cli_context *netlogon_creds,
3235 struct rpc_pipe_client **_rpccli)
3237 struct rpc_pipe_client *rpccli;
3238 struct pipe_auth_data *rpcauth;
3239 const char *target_service = table->authservices->names[0];
3240 struct cli_credentials *cli_creds;
3241 enum dcerpc_AuthLevel auth_level;
3242 NTSTATUS status;
3244 status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
3245 if (!NT_STATUS_IS_OK(status)) {
3246 return status;
3249 auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
3251 status = netlogon_creds_bind_cli_credentials(
3252 netlogon_creds, rpccli, &cli_creds);
3253 if (!NT_STATUS_IS_OK(status)) {
3254 DBG_DEBUG("netlogon_creds_bind_cli_credentials failed: %s\n",
3255 nt_errstr(status));
3256 TALLOC_FREE(rpccli);
3257 return status;
3260 status = rpccli_generic_bind_data_from_creds(rpccli,
3261 DCERPC_AUTH_TYPE_SCHANNEL,
3262 auth_level,
3263 rpccli->desthost,
3264 target_service,
3265 cli_creds,
3266 &rpcauth);
3267 if (!NT_STATUS_IS_OK(status)) {
3268 DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
3269 nt_errstr(status)));
3270 TALLOC_FREE(rpccli);
3271 return status;
3274 status = rpc_pipe_bind(rpccli, rpcauth);
3276 /* No TALLOC_FREE, gensec takes references */
3277 talloc_unlink(rpccli, cli_creds);
3278 cli_creds = NULL;
3280 if (!NT_STATUS_IS_OK(status)) {
3281 DBG_DEBUG("rpc_pipe_bind failed with error %s\n",
3282 nt_errstr(status));
3283 TALLOC_FREE(rpccli);
3284 return status;
3287 *_rpccli = rpccli;
3289 return NT_STATUS_OK;
3292 NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
3293 const struct ndr_interface_table *table,
3294 enum dcerpc_transport_t transport,
3295 struct netlogon_creds_cli_context *netlogon_creds,
3296 struct rpc_pipe_client **_rpccli)
3298 TALLOC_CTX *frame = talloc_stackframe();
3299 struct rpc_pipe_client *rpccli;
3300 struct netlogon_creds_cli_lck *lck;
3301 NTSTATUS status;
3303 status = netlogon_creds_cli_lck(
3304 netlogon_creds, NETLOGON_CREDS_CLI_LCK_EXCLUSIVE,
3305 frame, &lck);
3306 if (!NT_STATUS_IS_OK(status)) {
3307 DBG_WARNING("netlogon_creds_cli_lck returned %s\n",
3308 nt_errstr(status));
3309 TALLOC_FREE(frame);
3310 return status;
3313 status = cli_rpc_pipe_open_bind_schannel(
3314 cli, table, transport, netlogon_creds, &rpccli);
3315 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3316 netlogon_creds_cli_delete_lck(netlogon_creds);
3318 if (!NT_STATUS_IS_OK(status)) {
3319 DBG_DEBUG("cli_rpc_pipe_open_bind_schannel failed: %s\n",
3320 nt_errstr(status));
3321 TALLOC_FREE(frame);
3322 return status;
3325 if (ndr_syntax_id_equal(&table->syntax_id,
3326 &ndr_table_netlogon.syntax_id)) {
3327 status = netlogon_creds_cli_check(netlogon_creds,
3328 rpccli->binding_handle,
3329 NULL);
3330 if (!NT_STATUS_IS_OK(status)) {
3331 DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
3332 nt_errstr(status)));
3333 TALLOC_FREE(frame);
3334 return status;
3338 DBG_DEBUG("opened pipe %s to machine %s with key %s "
3339 "and bound using schannel.\n",
3340 table->name, rpccli->desthost,
3341 netlogon_creds_cli_debug_string(netlogon_creds, lck));
3343 TALLOC_FREE(frame);
3345 *_rpccli = rpccli;
3346 return NT_STATUS_OK;
3349 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3350 struct rpc_pipe_client *cli,
3351 DATA_BLOB *session_key)
3353 NTSTATUS status;
3354 struct pipe_auth_data *a;
3355 struct gensec_security *gensec_security;
3356 DATA_BLOB sk = data_blob_null;
3357 bool make_dup = false;
3359 if (!session_key || !cli) {
3360 return NT_STATUS_INVALID_PARAMETER;
3363 a = cli->auth;
3365 if (a == NULL) {
3366 return NT_STATUS_INVALID_PARAMETER;
3369 switch (cli->auth->auth_type) {
3370 case DCERPC_AUTH_TYPE_NONE:
3371 sk = data_blob_const(a->transport_session_key.data,
3372 a->transport_session_key.length);
3373 make_dup = true;
3374 break;
3375 default:
3376 gensec_security = a->auth_ctx;
3377 status = gensec_session_key(gensec_security, mem_ctx, &sk);
3378 if (!NT_STATUS_IS_OK(status)) {
3379 return status;
3381 make_dup = false;
3382 break;
3385 if (!sk.data) {
3386 return NT_STATUS_NO_USER_SESSION_KEY;
3389 if (make_dup) {
3390 *session_key = data_blob_dup_talloc(mem_ctx, sk);
3391 } else {
3392 *session_key = sk;
3395 return NT_STATUS_OK;