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/>.
23 #include "../lib/util/tevent_ntstatus.h"
24 #include "librpc/gen_ndr/ndr_epmapper_c.h"
25 #include "../librpc/gen_ndr/ndr_dssetup.h"
26 #include "../libcli/auth/schannel.h"
27 #include "../libcli/auth/netlogon_creds_cli.h"
28 #include "auth_generic.h"
29 #include "librpc/gen_ndr/ndr_dcerpc.h"
30 #include "librpc/gen_ndr/ndr_netlogon_c.h"
31 #include "librpc/rpc/dcerpc.h"
34 #include "libsmb/libsmb.h"
35 #include "auth/gensec/gensec.h"
36 #include "auth/credentials/credentials.h"
37 #include "../libcli/smb/smbXcli_base.h"
40 #define DBGC_CLASS DBGC_RPC_CLI
42 /********************************************************************
43 Pipe description for a DEBUG
44 ********************************************************************/
45 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
46 struct rpc_pipe_client *cli)
48 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
55 /********************************************************************
57 ********************************************************************/
59 static uint32_t get_rpc_call_id(void)
61 static uint32_t call_id = 0;
65 /*******************************************************************
66 Use SMBreadX to get rest of one fragment's worth of rpc data.
67 Reads the whole size or give an error message
68 ********************************************************************/
70 struct rpc_read_state {
71 struct tevent_context *ev;
72 struct rpc_cli_transport *transport;
78 static void rpc_read_done(struct tevent_req *subreq);
80 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
81 struct tevent_context *ev,
82 struct rpc_cli_transport *transport,
83 uint8_t *data, size_t size)
85 struct tevent_req *req, *subreq;
86 struct rpc_read_state *state;
88 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
93 state->transport = transport;
98 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
100 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
102 if (subreq == NULL) {
105 tevent_req_set_callback(subreq, rpc_read_done, req);
113 static void rpc_read_done(struct tevent_req *subreq)
115 struct tevent_req *req = tevent_req_callback_data(
116 subreq, struct tevent_req);
117 struct rpc_read_state *state = tevent_req_data(
118 req, struct rpc_read_state);
122 status = state->transport->read_recv(subreq, &received);
124 if (!NT_STATUS_IS_OK(status)) {
125 tevent_req_nterror(req, status);
129 state->num_read += received;
130 if (state->num_read == state->size) {
131 tevent_req_done(req);
135 subreq = state->transport->read_send(state, state->ev,
136 state->data + state->num_read,
137 state->size - state->num_read,
138 state->transport->priv);
139 if (tevent_req_nomem(subreq, req)) {
142 tevent_req_set_callback(subreq, rpc_read_done, req);
145 static NTSTATUS rpc_read_recv(struct tevent_req *req)
147 return tevent_req_simple_recv_ntstatus(req);
150 struct rpc_write_state {
151 struct tevent_context *ev;
152 struct rpc_cli_transport *transport;
158 static void rpc_write_done(struct tevent_req *subreq);
160 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
161 struct tevent_context *ev,
162 struct rpc_cli_transport *transport,
163 const uint8_t *data, size_t size)
165 struct tevent_req *req, *subreq;
166 struct rpc_write_state *state;
168 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
173 state->transport = transport;
176 state->num_written = 0;
178 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
180 subreq = transport->write_send(state, ev, data, size, transport->priv);
181 if (subreq == NULL) {
184 tevent_req_set_callback(subreq, rpc_write_done, req);
191 static void rpc_write_done(struct tevent_req *subreq)
193 struct tevent_req *req = tevent_req_callback_data(
194 subreq, struct tevent_req);
195 struct rpc_write_state *state = tevent_req_data(
196 req, struct rpc_write_state);
200 status = state->transport->write_recv(subreq, &written);
202 if (!NT_STATUS_IS_OK(status)) {
203 tevent_req_nterror(req, status);
207 state->num_written += written;
209 if (state->num_written == state->size) {
210 tevent_req_done(req);
214 subreq = state->transport->write_send(state, state->ev,
215 state->data + state->num_written,
216 state->size - state->num_written,
217 state->transport->priv);
218 if (tevent_req_nomem(subreq, req)) {
221 tevent_req_set_callback(subreq, rpc_write_done, req);
224 static NTSTATUS rpc_write_recv(struct tevent_req *req)
226 return tevent_req_simple_recv_ntstatus(req);
230 /****************************************************************************
231 Try and get a PDU's worth of data from current_pdu. If not, then read more
233 ****************************************************************************/
235 struct get_complete_frag_state {
236 struct tevent_context *ev;
237 struct rpc_pipe_client *cli;
242 static void get_complete_frag_got_header(struct tevent_req *subreq);
243 static void get_complete_frag_got_rest(struct tevent_req *subreq);
245 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
246 struct tevent_context *ev,
247 struct rpc_pipe_client *cli,
250 struct tevent_req *req, *subreq;
251 struct get_complete_frag_state *state;
255 req = tevent_req_create(mem_ctx, &state,
256 struct get_complete_frag_state);
262 state->frag_len = RPC_HEADER_LEN;
265 received = pdu->length;
266 if (received < RPC_HEADER_LEN) {
267 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
268 status = NT_STATUS_NO_MEMORY;
271 subreq = rpc_read_send(state, state->ev,
272 state->cli->transport,
273 pdu->data + received,
274 RPC_HEADER_LEN - received);
275 if (subreq == NULL) {
276 status = NT_STATUS_NO_MEMORY;
279 tevent_req_set_callback(subreq, get_complete_frag_got_header,
284 state->frag_len = dcerpc_get_frag_length(pdu);
285 if (state->frag_len < RPC_HEADER_LEN) {
286 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
287 return tevent_req_post(req, ev);
291 * Ensure we have frag_len bytes of data.
293 if (received < state->frag_len) {
294 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
295 status = NT_STATUS_NO_MEMORY;
298 subreq = rpc_read_send(state, state->ev,
299 state->cli->transport,
300 pdu->data + received,
301 state->frag_len - received);
302 if (subreq == NULL) {
303 status = NT_STATUS_NO_MEMORY;
306 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
311 status = NT_STATUS_OK;
313 if (NT_STATUS_IS_OK(status)) {
314 tevent_req_done(req);
316 tevent_req_nterror(req, status);
318 return tevent_req_post(req, ev);
321 static void get_complete_frag_got_header(struct tevent_req *subreq)
323 struct tevent_req *req = tevent_req_callback_data(
324 subreq, struct tevent_req);
325 struct get_complete_frag_state *state = tevent_req_data(
326 req, struct get_complete_frag_state);
329 status = rpc_read_recv(subreq);
331 if (!NT_STATUS_IS_OK(status)) {
332 tevent_req_nterror(req, status);
336 state->frag_len = dcerpc_get_frag_length(state->pdu);
337 if (state->frag_len < RPC_HEADER_LEN) {
338 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
342 if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
343 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
348 * We're here in this piece of code because we've read exactly
349 * RPC_HEADER_LEN bytes into state->pdu.
352 subreq = rpc_read_send(state, state->ev, state->cli->transport,
353 state->pdu->data + RPC_HEADER_LEN,
354 state->frag_len - RPC_HEADER_LEN);
355 if (tevent_req_nomem(subreq, req)) {
358 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
361 static void get_complete_frag_got_rest(struct tevent_req *subreq)
363 struct tevent_req *req = tevent_req_callback_data(
364 subreq, struct tevent_req);
367 status = rpc_read_recv(subreq);
369 if (!NT_STATUS_IS_OK(status)) {
370 tevent_req_nterror(req, status);
373 tevent_req_done(req);
376 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
378 return tevent_req_simple_recv_ntstatus(req);
381 /****************************************************************************
382 Do basic authentication checks on an incoming pdu.
383 ****************************************************************************/
385 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
386 struct rpc_pipe_client *cli,
387 struct ncacn_packet *pkt,
389 uint8_t expected_pkt_type,
392 DATA_BLOB *reply_pdu)
394 const struct dcerpc_response *r = NULL;
395 DATA_BLOB tmp_stub = data_blob_null;
396 NTSTATUS ret = NT_STATUS_OK;
399 * Point the return values at the real data including the RPC
400 * header. Just in case the caller wants it.
404 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
405 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
407 * TODO: do we still need this hack which was introduced
408 * in commit a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0.
410 * I don't even know what AS/U might be...
412 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
413 "fragment first/last ON.\n"));
414 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
417 /* Ensure we have the correct type. */
418 switch (pkt->ptype) {
419 case DCERPC_PKT_BIND_NAK:
420 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
421 rpccli_pipe_txt(talloc_tos(), cli)));
423 ret = dcerpc_verify_ncacn_packet_header(pkt,
425 0, /* max_auth_info */
426 DCERPC_PFC_FLAG_FIRST |
427 DCERPC_PFC_FLAG_LAST,
428 0); /* optional flags */
429 if (!NT_STATUS_IS_OK(ret)) {
430 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
431 "RPC packet type - %u, expected %u: %s\n",
432 rpccli_pipe_txt(talloc_tos(), cli),
433 pkt->ptype, expected_pkt_type,
435 NDR_PRINT_DEBUG(ncacn_packet, pkt);
439 /* Use this for now... */
440 return NT_STATUS_NETWORK_ACCESS_DENIED;
442 case DCERPC_PKT_BIND_ACK:
443 ret = dcerpc_verify_ncacn_packet_header(pkt,
445 pkt->u.bind_ack.auth_info.length,
446 DCERPC_PFC_FLAG_FIRST |
447 DCERPC_PFC_FLAG_LAST,
448 DCERPC_PFC_FLAG_CONC_MPX |
449 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
450 if (!NT_STATUS_IS_OK(ret)) {
451 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
452 "RPC packet type - %u, expected %u: %s\n",
453 rpccli_pipe_txt(talloc_tos(), cli),
454 pkt->ptype, expected_pkt_type,
456 NDR_PRINT_DEBUG(ncacn_packet, pkt);
462 case DCERPC_PKT_ALTER_RESP:
463 ret = dcerpc_verify_ncacn_packet_header(pkt,
465 pkt->u.alter_resp.auth_info.length,
466 DCERPC_PFC_FLAG_FIRST |
467 DCERPC_PFC_FLAG_LAST,
468 DCERPC_PFC_FLAG_CONC_MPX |
469 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
470 if (!NT_STATUS_IS_OK(ret)) {
471 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
472 "RPC packet type - %u, expected %u: %s\n",
473 rpccli_pipe_txt(talloc_tos(), cli),
474 pkt->ptype, expected_pkt_type,
476 NDR_PRINT_DEBUG(ncacn_packet, pkt);
482 case DCERPC_PKT_RESPONSE:
484 r = &pkt->u.response;
486 ret = dcerpc_verify_ncacn_packet_header(pkt,
488 r->stub_and_verifier.length,
489 0, /* required_flags */
490 DCERPC_PFC_FLAG_FIRST |
491 DCERPC_PFC_FLAG_LAST);
492 if (!NT_STATUS_IS_OK(ret)) {
493 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
494 "RPC packet type - %u, expected %u: %s\n",
495 rpccli_pipe_txt(talloc_tos(), cli),
496 pkt->ptype, expected_pkt_type,
498 NDR_PRINT_DEBUG(ncacn_packet, pkt);
502 tmp_stub.data = r->stub_and_verifier.data;
503 tmp_stub.length = r->stub_and_verifier.length;
505 /* Here's where we deal with incoming sign/seal. */
506 ret = dcerpc_check_auth(cli->auth, pkt,
508 DCERPC_RESPONSE_LENGTH,
510 if (!NT_STATUS_IS_OK(ret)) {
511 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
512 "RPC packet type - %u, expected %u: %s\n",
513 rpccli_pipe_txt(talloc_tos(), cli),
514 pkt->ptype, expected_pkt_type,
516 NDR_PRINT_DEBUG(ncacn_packet, pkt);
520 /* Point the return values at the NDR data. */
523 DEBUG(10, ("Got pdu len %lu, data_len %lu\n",
524 (long unsigned int)pdu->length,
525 (long unsigned int)rdata->length));
528 * If this is the first reply, and the allocation hint is
529 * reasonable, try and set up the reply_pdu DATA_BLOB to the
533 if ((reply_pdu->length == 0) &&
534 r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
535 if (!data_blob_realloc(mem_ctx, reply_pdu,
537 DEBUG(0, ("reply alloc hint %d too "
538 "large to allocate\n",
539 (int)r->alloc_hint));
540 return NT_STATUS_NO_MEMORY;
546 case DCERPC_PKT_FAULT:
548 ret = dcerpc_verify_ncacn_packet_header(pkt,
550 0, /* max_auth_info */
551 DCERPC_PFC_FLAG_FIRST |
552 DCERPC_PFC_FLAG_LAST,
553 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
554 if (!NT_STATUS_IS_OK(ret)) {
555 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
556 "RPC packet type - %u, expected %u: %s\n",
557 rpccli_pipe_txt(talloc_tos(), cli),
558 pkt->ptype, expected_pkt_type,
560 NDR_PRINT_DEBUG(ncacn_packet, pkt);
564 DEBUG(1, (__location__ ": RPC fault code %s received "
566 dcerpc_errstr(talloc_tos(),
567 pkt->u.fault.status),
568 rpccli_pipe_txt(talloc_tos(), cli)));
570 return dcerpc_fault_to_nt_status(pkt->u.fault.status);
573 DEBUG(0, (__location__ "Unknown packet type %u received "
575 (unsigned int)pkt->ptype,
576 rpccli_pipe_txt(talloc_tos(), cli)));
577 return NT_STATUS_RPC_PROTOCOL_ERROR;
581 if (pkt->call_id != call_id) {
582 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
583 "RPC call_id - %u, not %u\n",
584 rpccli_pipe_txt(talloc_tos(), cli),
585 pkt->call_id, call_id));
586 return NT_STATUS_RPC_PROTOCOL_ERROR;
592 /****************************************************************************
593 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
594 ****************************************************************************/
596 struct cli_api_pipe_state {
597 struct tevent_context *ev;
598 struct rpc_cli_transport *transport;
603 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
604 static void cli_api_pipe_write_done(struct tevent_req *subreq);
605 static void cli_api_pipe_read_done(struct tevent_req *subreq);
607 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
608 struct tevent_context *ev,
609 struct rpc_cli_transport *transport,
610 uint8_t *data, size_t data_len,
611 uint32_t max_rdata_len)
613 struct tevent_req *req, *subreq;
614 struct cli_api_pipe_state *state;
617 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
622 state->transport = transport;
624 if (max_rdata_len < RPC_HEADER_LEN) {
626 * For a RPC reply we always need at least RPC_HEADER_LEN
627 * bytes. We check this here because we will receive
628 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
630 status = NT_STATUS_INVALID_PARAMETER;
634 if (transport->trans_send != NULL) {
635 subreq = transport->trans_send(state, ev, data, data_len,
636 max_rdata_len, transport->priv);
637 if (subreq == NULL) {
640 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
645 * If the transport does not provide a "trans" routine, i.e. for
646 * example the ncacn_ip_tcp transport, do the write/read step here.
649 subreq = rpc_write_send(state, ev, transport, data, data_len);
650 if (subreq == NULL) {
653 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
657 tevent_req_nterror(req, status);
658 return tevent_req_post(req, ev);
664 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
666 struct tevent_req *req = tevent_req_callback_data(
667 subreq, struct tevent_req);
668 struct cli_api_pipe_state *state = tevent_req_data(
669 req, struct cli_api_pipe_state);
672 status = state->transport->trans_recv(subreq, state, &state->rdata,
675 if (!NT_STATUS_IS_OK(status)) {
676 tevent_req_nterror(req, status);
679 tevent_req_done(req);
682 static void cli_api_pipe_write_done(struct tevent_req *subreq)
684 struct tevent_req *req = tevent_req_callback_data(
685 subreq, struct tevent_req);
686 struct cli_api_pipe_state *state = tevent_req_data(
687 req, struct cli_api_pipe_state);
690 status = rpc_write_recv(subreq);
692 if (!NT_STATUS_IS_OK(status)) {
693 tevent_req_nterror(req, status);
697 state->rdata = talloc_array(state, uint8_t, RPC_HEADER_LEN);
698 if (tevent_req_nomem(state->rdata, req)) {
703 * We don't need to use rpc_read_send here, the upper layer will cope
704 * with a short read, transport->trans_send could also return less
705 * than state->max_rdata_len.
707 subreq = state->transport->read_send(state, state->ev, state->rdata,
709 state->transport->priv);
710 if (tevent_req_nomem(subreq, req)) {
713 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
716 static void cli_api_pipe_read_done(struct tevent_req *subreq)
718 struct tevent_req *req = tevent_req_callback_data(
719 subreq, struct tevent_req);
720 struct cli_api_pipe_state *state = tevent_req_data(
721 req, struct cli_api_pipe_state);
725 status = state->transport->read_recv(subreq, &received);
727 if (!NT_STATUS_IS_OK(status)) {
728 tevent_req_nterror(req, status);
731 state->rdata_len = received;
732 tevent_req_done(req);
735 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
736 uint8_t **prdata, uint32_t *prdata_len)
738 struct cli_api_pipe_state *state = tevent_req_data(
739 req, struct cli_api_pipe_state);
742 if (tevent_req_is_nterror(req, &status)) {
746 *prdata = talloc_move(mem_ctx, &state->rdata);
747 *prdata_len = state->rdata_len;
751 /****************************************************************************
752 Send data on an rpc pipe via trans. The data must be the last
753 pdu fragment of an NDR data stream.
755 Receive response data from an rpc pipe, which may be large...
757 Read the first fragment: unfortunately have to use SMBtrans for the first
758 bit, then SMBreadX for subsequent bits.
760 If first fragment received also wasn't the last fragment, continue
761 getting fragments until we _do_ receive the last fragment.
763 Request/Response PDU's look like the following...
765 |<------------------PDU len----------------------------------------------->|
766 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
768 +------------+-----------------+-------------+---------------+-------------+
769 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
770 +------------+-----------------+-------------+---------------+-------------+
772 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
773 signing & sealing being negotiated.
775 ****************************************************************************/
777 struct rpc_api_pipe_state {
778 struct tevent_context *ev;
779 struct rpc_pipe_client *cli;
780 uint8_t expected_pkt_type;
783 DATA_BLOB incoming_frag;
784 struct ncacn_packet *pkt;
788 size_t reply_pdu_offset;
792 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
793 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
794 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq);
796 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
797 struct tevent_context *ev,
798 struct rpc_pipe_client *cli,
799 DATA_BLOB *data, /* Outgoing PDU */
800 uint8_t expected_pkt_type,
803 struct tevent_req *req, *subreq;
804 struct rpc_api_pipe_state *state;
805 uint16_t max_recv_frag;
808 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
814 state->expected_pkt_type = expected_pkt_type;
815 state->call_id = call_id;
816 state->endianess = DCERPC_DREP_LE;
819 * Ensure we're not sending too much.
821 if (data->length > cli->max_xmit_frag) {
822 status = NT_STATUS_INVALID_PARAMETER;
826 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
828 if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
829 subreq = rpc_write_send(state, ev, cli->transport,
830 data->data, data->length);
831 if (subreq == NULL) {
834 tevent_req_set_callback(subreq, rpc_api_pipe_auth3_done, req);
838 /* get the header first, then fetch the rest once we have
839 * the frag_length available */
840 max_recv_frag = RPC_HEADER_LEN;
842 subreq = cli_api_pipe_send(state, ev, cli->transport,
843 data->data, data->length, max_recv_frag);
844 if (subreq == NULL) {
847 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
851 tevent_req_nterror(req, status);
852 return tevent_req_post(req, ev);
858 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq)
860 struct tevent_req *req =
861 tevent_req_callback_data(subreq,
865 status = rpc_write_recv(subreq);
867 if (!NT_STATUS_IS_OK(status)) {
868 tevent_req_nterror(req, status);
872 tevent_req_done(req);
875 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
877 struct tevent_req *req = tevent_req_callback_data(
878 subreq, struct tevent_req);
879 struct rpc_api_pipe_state *state = tevent_req_data(
880 req, struct rpc_api_pipe_state);
882 uint8_t *rdata = NULL;
883 uint32_t rdata_len = 0;
885 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
887 if (!NT_STATUS_IS_OK(status)) {
888 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
889 tevent_req_nterror(req, status);
894 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
895 rpccli_pipe_txt(talloc_tos(), state->cli)));
896 tevent_req_done(req);
901 * Move data on state->incoming_frag.
903 state->incoming_frag.data = talloc_move(state, &rdata);
904 state->incoming_frag.length = rdata_len;
905 if (!state->incoming_frag.data) {
906 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
910 /* Ensure we have enough data for a pdu. */
911 subreq = get_complete_frag_send(state, state->ev, state->cli,
912 &state->incoming_frag);
913 if (tevent_req_nomem(subreq, req)) {
916 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
919 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
921 struct tevent_req *req = tevent_req_callback_data(
922 subreq, struct tevent_req);
923 struct rpc_api_pipe_state *state = tevent_req_data(
924 req, struct rpc_api_pipe_state);
926 DATA_BLOB rdata = data_blob_null;
928 status = get_complete_frag_recv(subreq);
930 if (!NT_STATUS_IS_OK(status)) {
931 DEBUG(5, ("get_complete_frag failed: %s\n",
933 tevent_req_nterror(req, status);
937 state->pkt = talloc(state, struct ncacn_packet);
939 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
943 status = dcerpc_pull_ncacn_packet(state->pkt,
944 &state->incoming_frag,
947 if (!NT_STATUS_IS_OK(status)) {
948 tevent_req_nterror(req, status);
952 status = cli_pipe_validate_current_pdu(state,
953 state->cli, state->pkt,
954 &state->incoming_frag,
955 state->expected_pkt_type,
960 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
961 (unsigned)state->incoming_frag.length,
962 (unsigned)state->reply_pdu_offset,
965 if (!NT_STATUS_IS_OK(status)) {
966 tevent_req_nterror(req, status);
970 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
971 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
973 * Set the data type correctly for big-endian data on the
976 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
978 rpccli_pipe_txt(talloc_tos(), state->cli)));
979 state->endianess = 0x00; /* BIG ENDIAN */
982 * Check endianness on subsequent packets.
984 if (state->endianess != state->pkt->drep[0]) {
985 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
987 state->endianess?"little":"big",
988 state->pkt->drep[0]?"little":"big"));
989 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
993 if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) {
994 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
998 /* Now copy the data portion out of the pdu into rbuf. */
999 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
1000 if (!data_blob_realloc(NULL, &state->reply_pdu,
1001 state->reply_pdu_offset + rdata.length)) {
1002 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1007 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
1008 rdata.data, rdata.length);
1009 state->reply_pdu_offset += rdata.length;
1011 /* reset state->incoming_frag, there is no need to free it,
1012 * it will be reallocated to the right size the next time
1014 state->incoming_frag.length = 0;
1016 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1017 /* make sure the pdu length is right now that we
1018 * have all the data available (alloc hint may
1019 * have allocated more than was actually used) */
1020 state->reply_pdu.length = state->reply_pdu_offset;
1021 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1022 rpccli_pipe_txt(talloc_tos(), state->cli),
1023 (unsigned)state->reply_pdu.length));
1024 tevent_req_done(req);
1028 subreq = get_complete_frag_send(state, state->ev, state->cli,
1029 &state->incoming_frag);
1030 if (tevent_req_nomem(subreq, req)) {
1033 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1036 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1037 struct ncacn_packet **pkt,
1038 DATA_BLOB *reply_pdu)
1040 struct rpc_api_pipe_state *state = tevent_req_data(
1041 req, struct rpc_api_pipe_state);
1044 if (tevent_req_is_nterror(req, &status)) {
1048 /* return data to caller and assign it ownership of memory */
1050 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1051 reply_pdu->length = state->reply_pdu.length;
1052 state->reply_pdu.length = 0;
1054 data_blob_free(&state->reply_pdu);
1058 *pkt = talloc_steal(mem_ctx, state->pkt);
1061 return NT_STATUS_OK;
1064 /*******************************************************************
1065 Creates NTLMSSP auth bind.
1066 ********************************************************************/
1068 static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1069 TALLOC_CTX *mem_ctx,
1070 DATA_BLOB *auth_token,
1071 bool *client_hdr_signing)
1073 struct gensec_security *gensec_security;
1074 DATA_BLOB null_blob = data_blob_null;
1077 gensec_security = cli->auth->auth_ctx;
1079 DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
1080 status = gensec_update(gensec_security, mem_ctx, null_blob, auth_token);
1082 if (!NT_STATUS_IS_OK(status) &&
1083 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1088 if (client_hdr_signing == NULL) {
1092 if (cli->auth->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1093 *client_hdr_signing = false;
1097 *client_hdr_signing = gensec_have_feature(gensec_security,
1098 GENSEC_FEATURE_SIGN_PKT_HEADER);
1103 /*******************************************************************
1104 Creates the internals of a DCE/RPC bind request or alter context PDU.
1105 ********************************************************************/
1107 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1108 enum dcerpc_pkt_type ptype,
1109 uint32_t rpc_call_id,
1110 const struct ndr_syntax_id *abstract,
1111 const struct ndr_syntax_id *transfer,
1112 const DATA_BLOB *auth_info,
1113 bool client_hdr_signing,
1116 uint16_t auth_len = auth_info->length;
1118 union dcerpc_payload u;
1119 struct dcerpc_ctx_list ctx_list;
1120 uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1123 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1126 if (client_hdr_signing) {
1127 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1130 ctx_list.context_id = 0;
1131 ctx_list.num_transfer_syntaxes = 1;
1132 ctx_list.abstract_syntax = *abstract;
1133 ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1135 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1136 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1137 u.bind.assoc_group_id = 0x0;
1138 u.bind.num_contexts = 1;
1139 u.bind.ctx_list = &ctx_list;
1140 u.bind.auth_info = *auth_info;
1142 status = dcerpc_push_ncacn_packet(mem_ctx,
1148 if (!NT_STATUS_IS_OK(status)) {
1149 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1153 return NT_STATUS_OK;
1156 /*******************************************************************
1157 Creates a DCE/RPC bind request.
1158 ********************************************************************/
1160 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1161 struct rpc_pipe_client *cli,
1162 struct pipe_auth_data *auth,
1163 uint32_t rpc_call_id,
1164 const struct ndr_syntax_id *abstract,
1165 const struct ndr_syntax_id *transfer,
1168 DATA_BLOB auth_token = data_blob_null;
1169 DATA_BLOB auth_info = data_blob_null;
1170 NTSTATUS ret = NT_STATUS_OK;
1172 switch (auth->auth_type) {
1173 case DCERPC_AUTH_TYPE_NONE:
1177 ret = create_generic_auth_rpc_bind_req(cli, mem_ctx,
1179 &auth->client_hdr_signing);
1181 if (!NT_STATUS_IS_OK(ret) &&
1182 !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1188 if (auth_token.length != 0) {
1189 ret = dcerpc_push_dcerpc_auth(cli,
1192 0, /* auth_pad_length */
1193 auth->auth_context_id,
1196 if (!NT_STATUS_IS_OK(ret)) {
1199 data_blob_free(&auth_token);
1202 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1208 auth->client_hdr_signing,
1213 /*******************************************************************
1215 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1216 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1217 and deals with signing/sealing details.
1218 ********************************************************************/
1220 struct rpc_api_pipe_req_state {
1221 struct tevent_context *ev;
1222 struct rpc_pipe_client *cli;
1225 const DATA_BLOB *req_data;
1226 uint32_t req_data_sent;
1227 DATA_BLOB req_trailer;
1228 uint32_t req_trailer_sent;
1229 bool verify_bitmask1;
1230 bool verify_pcontext;
1232 DATA_BLOB reply_pdu;
1235 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1236 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1237 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state);
1238 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1239 bool *is_last_frag);
1241 static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1242 struct tevent_context *ev,
1243 struct rpc_pipe_client *cli,
1245 const DATA_BLOB *req_data)
1247 struct tevent_req *req, *subreq;
1248 struct rpc_api_pipe_req_state *state;
1252 req = tevent_req_create(mem_ctx, &state,
1253 struct rpc_api_pipe_req_state);
1259 state->op_num = op_num;
1260 state->req_data = req_data;
1261 state->req_data_sent = 0;
1262 state->call_id = get_rpc_call_id();
1263 state->reply_pdu = data_blob_null;
1264 state->rpc_out = data_blob_null;
1266 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1267 + RPC_MAX_SIGN_SIZE) {
1268 /* Server is screwed up ! */
1269 status = NT_STATUS_INVALID_PARAMETER;
1273 status = prepare_verification_trailer(state);
1274 if (!NT_STATUS_IS_OK(status)) {
1278 status = prepare_next_frag(state, &is_last_frag);
1279 if (!NT_STATUS_IS_OK(status)) {
1284 subreq = rpc_api_pipe_send(state, ev, state->cli,
1286 DCERPC_PKT_RESPONSE,
1288 if (subreq == NULL) {
1291 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1293 subreq = rpc_write_send(state, ev, cli->transport,
1294 state->rpc_out.data,
1295 state->rpc_out.length);
1296 if (subreq == NULL) {
1299 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1305 tevent_req_nterror(req, status);
1306 return tevent_req_post(req, ev);
1312 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state)
1314 struct pipe_auth_data *a = state->cli->auth;
1315 struct dcerpc_sec_verification_trailer *t;
1316 struct dcerpc_sec_vt *c = NULL;
1317 struct ndr_push *ndr = NULL;
1318 enum ndr_err_code ndr_err;
1323 return NT_STATUS_OK;
1326 if (a->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1327 return NT_STATUS_OK;
1330 t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1332 return NT_STATUS_NO_MEMORY;
1335 if (!a->verified_bitmask1) {
1336 t->commands = talloc_realloc(t, t->commands,
1337 struct dcerpc_sec_vt,
1338 t->count.count + 1);
1339 if (t->commands == NULL) {
1340 return NT_STATUS_NO_MEMORY;
1342 c = &t->commands[t->count.count++];
1345 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1346 if (a->client_hdr_signing) {
1347 c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1349 state->verify_bitmask1 = true;
1352 if (!state->cli->verified_pcontext) {
1353 t->commands = talloc_realloc(t, t->commands,
1354 struct dcerpc_sec_vt,
1355 t->count.count + 1);
1356 if (t->commands == NULL) {
1357 return NT_STATUS_NO_MEMORY;
1359 c = &t->commands[t->count.count++];
1362 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1363 c->u.pcontext.abstract_syntax = state->cli->abstract_syntax;
1364 c->u.pcontext.transfer_syntax = state->cli->transfer_syntax;
1366 state->verify_pcontext = true;
1369 if (!a->hdr_signing) {
1370 t->commands = talloc_realloc(t, t->commands,
1371 struct dcerpc_sec_vt,
1372 t->count.count + 1);
1373 if (t->commands == NULL) {
1374 return NT_STATUS_NO_MEMORY;
1376 c = &t->commands[t->count.count++];
1379 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1380 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1381 c->u.header2.drep[0] = DCERPC_DREP_LE;
1382 c->u.header2.drep[1] = 0;
1383 c->u.header2.drep[2] = 0;
1384 c->u.header2.drep[3] = 0;
1385 c->u.header2.call_id = state->call_id;
1386 c->u.header2.context_id = 0;
1387 c->u.header2.opnum = state->op_num;
1390 if (t->count.count == 0) {
1392 return NT_STATUS_OK;
1395 c = &t->commands[t->count.count - 1];
1396 c->command |= DCERPC_SEC_VT_COMMAND_END;
1398 if (DEBUGLEVEL >= 10) {
1399 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1402 ndr = ndr_push_init_ctx(state);
1404 return NT_STATUS_NO_MEMORY;
1407 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1408 NDR_SCALARS | NDR_BUFFERS,
1410 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1411 return ndr_map_error2ntstatus(ndr_err);
1413 state->req_trailer = ndr_push_blob(ndr);
1415 align = state->req_data->length & 0x3;
1422 const uint8_t zeros[4] = { 0, };
1424 ok = data_blob_append(ndr, &state->req_trailer, zeros, pad);
1426 return NT_STATUS_NO_MEMORY;
1429 /* move the padding to the start */
1430 p = state->req_trailer.data;
1431 memmove(p + pad, p, state->req_trailer.length - pad);
1435 return NT_STATUS_OK;
1438 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1446 size_t data_thistime;
1447 size_t trailer_left;
1448 size_t trailer_thistime = 0;
1450 size_t total_thistime;
1453 union dcerpc_payload u;
1455 data_left = state->req_data->length - state->req_data_sent;
1456 trailer_left = state->req_trailer.length - state->req_trailer_sent;
1457 total_left = data_left + trailer_left;
1458 if ((total_left < data_left) || (total_left < trailer_left)) {
1462 return NT_STATUS_INVALID_PARAMETER_MIX;
1465 status = dcerpc_guess_sizes(state->cli->auth,
1466 DCERPC_REQUEST_LENGTH, total_left,
1467 state->cli->max_xmit_frag,
1469 &frag_len, &auth_len, &pad_len);
1470 if (!NT_STATUS_IS_OK(status)) {
1474 if (state->req_data_sent == 0) {
1475 flags = DCERPC_PFC_FLAG_FIRST;
1478 if (total_thistime == total_left) {
1479 flags |= DCERPC_PFC_FLAG_LAST;
1482 data_thistime = MIN(total_thistime, data_left);
1483 if (data_thistime < total_thistime) {
1484 trailer_thistime = total_thistime - data_thistime;
1487 data_blob_free(&state->rpc_out);
1489 ZERO_STRUCT(u.request);
1491 u.request.alloc_hint = total_left;
1492 u.request.context_id = 0;
1493 u.request.opnum = state->op_num;
1495 status = dcerpc_push_ncacn_packet(state,
1502 if (!NT_STATUS_IS_OK(status)) {
1506 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1507 * compute it right for requests because the auth trailer is missing
1509 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1511 if (data_thistime > 0) {
1512 /* Copy in the data. */
1513 ok = data_blob_append(NULL, &state->rpc_out,
1514 state->req_data->data + state->req_data_sent,
1517 return NT_STATUS_NO_MEMORY;
1519 state->req_data_sent += data_thistime;
1522 if (trailer_thistime > 0) {
1523 /* Copy in the verification trailer. */
1524 ok = data_blob_append(NULL, &state->rpc_out,
1525 state->req_trailer.data + state->req_trailer_sent,
1528 return NT_STATUS_NO_MEMORY;
1530 state->req_trailer_sent += trailer_thistime;
1533 switch (state->cli->auth->auth_level) {
1534 case DCERPC_AUTH_LEVEL_NONE:
1535 case DCERPC_AUTH_LEVEL_CONNECT:
1536 case DCERPC_AUTH_LEVEL_PACKET:
1538 case DCERPC_AUTH_LEVEL_INTEGRITY:
1539 case DCERPC_AUTH_LEVEL_PRIVACY:
1540 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1542 if (!NT_STATUS_IS_OK(status)) {
1547 return NT_STATUS_INVALID_PARAMETER;
1550 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1555 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1557 struct tevent_req *req = tevent_req_callback_data(
1558 subreq, struct tevent_req);
1559 struct rpc_api_pipe_req_state *state = tevent_req_data(
1560 req, struct rpc_api_pipe_req_state);
1564 status = rpc_write_recv(subreq);
1565 TALLOC_FREE(subreq);
1566 if (!NT_STATUS_IS_OK(status)) {
1567 tevent_req_nterror(req, status);
1571 status = prepare_next_frag(state, &is_last_frag);
1572 if (!NT_STATUS_IS_OK(status)) {
1573 tevent_req_nterror(req, status);
1578 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1580 DCERPC_PKT_RESPONSE,
1582 if (tevent_req_nomem(subreq, req)) {
1585 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1587 subreq = rpc_write_send(state, state->ev,
1588 state->cli->transport,
1589 state->rpc_out.data,
1590 state->rpc_out.length);
1591 if (tevent_req_nomem(subreq, req)) {
1594 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1599 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1601 struct tevent_req *req = tevent_req_callback_data(
1602 subreq, struct tevent_req);
1603 struct rpc_api_pipe_req_state *state = tevent_req_data(
1604 req, struct rpc_api_pipe_req_state);
1607 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1608 TALLOC_FREE(subreq);
1609 if (!NT_STATUS_IS_OK(status)) {
1610 tevent_req_nterror(req, status);
1614 if (state->cli->auth == NULL) {
1615 tevent_req_done(req);
1619 if (state->verify_bitmask1) {
1620 state->cli->auth->verified_bitmask1 = true;
1623 if (state->verify_pcontext) {
1624 state->cli->verified_pcontext = true;
1627 tevent_req_done(req);
1630 static NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1631 DATA_BLOB *reply_pdu)
1633 struct rpc_api_pipe_req_state *state = tevent_req_data(
1634 req, struct rpc_api_pipe_req_state);
1637 if (tevent_req_is_nterror(req, &status)) {
1639 * We always have to initialize to reply pdu, even if there is
1640 * none. The rpccli_* caller routines expect this.
1642 *reply_pdu = data_blob_null;
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;
1651 return NT_STATUS_OK;
1654 /****************************************************************************
1655 Check the rpc bind acknowledge response.
1656 ****************************************************************************/
1658 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1659 const struct ndr_syntax_id *transfer)
1661 struct dcerpc_ack_ctx ctx;
1663 if (r->secondary_address_size == 0) {
1664 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1667 if (r->num_results < 1 || !r->ctx_list) {
1671 ctx = r->ctx_list[0];
1673 /* check the transfer syntax */
1674 if ((ctx.syntax.if_version != transfer->if_version) ||
1675 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1676 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1680 if (r->num_results != 0x1 || ctx.result != 0) {
1681 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1682 r->num_results, ctx.reason.value));
1685 DEBUG(5,("check_bind_response: accepted!\n"));
1689 /*******************************************************************
1690 Creates a DCE/RPC bind authentication response.
1691 This is the packet that is sent back to the server once we
1692 have received a BIND-ACK, to finish the third leg of
1693 the authentication handshake.
1694 ********************************************************************/
1696 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1697 struct rpc_pipe_client *cli,
1698 struct pipe_auth_data *auth,
1699 uint32_t rpc_call_id,
1700 DATA_BLOB *pauth_blob,
1704 union dcerpc_payload u;
1708 status = dcerpc_push_dcerpc_auth(mem_ctx,
1711 0, /* auth_pad_length */
1712 auth->auth_context_id,
1714 &u.auth3.auth_info);
1715 if (!NT_STATUS_IS_OK(status)) {
1719 status = dcerpc_push_ncacn_packet(mem_ctx,
1721 DCERPC_PFC_FLAG_FIRST |
1722 DCERPC_PFC_FLAG_LAST,
1727 data_blob_free(&u.auth3.auth_info);
1728 if (!NT_STATUS_IS_OK(status)) {
1729 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1733 return NT_STATUS_OK;
1736 /*******************************************************************
1737 Creates a DCE/RPC bind alter context authentication request which
1738 may contain a spnego auth blobl
1739 ********************************************************************/
1741 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1742 struct pipe_auth_data *auth,
1743 uint32_t rpc_call_id,
1744 const struct ndr_syntax_id *abstract,
1745 const struct ndr_syntax_id *transfer,
1746 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1749 DATA_BLOB auth_info;
1752 status = dcerpc_push_dcerpc_auth(mem_ctx,
1755 0, /* auth_pad_length */
1756 auth->auth_context_id,
1759 if (!NT_STATUS_IS_OK(status)) {
1763 status = create_bind_or_alt_ctx_internal(mem_ctx,
1769 false, /* client_hdr_signing */
1771 data_blob_free(&auth_info);
1775 /****************************************************************************
1777 ****************************************************************************/
1779 struct rpc_pipe_bind_state {
1780 struct tevent_context *ev;
1781 struct rpc_pipe_client *cli;
1784 uint32_t rpc_call_id;
1787 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1788 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1789 struct rpc_pipe_bind_state *state,
1790 DATA_BLOB *credentials);
1791 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1792 struct rpc_pipe_bind_state *state,
1793 DATA_BLOB *credentials);
1795 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1796 struct tevent_context *ev,
1797 struct rpc_pipe_client *cli,
1798 struct pipe_auth_data *auth)
1800 struct tevent_req *req, *subreq;
1801 struct rpc_pipe_bind_state *state;
1804 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1809 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1810 rpccli_pipe_txt(talloc_tos(), cli),
1811 (unsigned int)auth->auth_type,
1812 (unsigned int)auth->auth_level ));
1816 state->rpc_call_id = get_rpc_call_id();
1818 cli->auth = talloc_move(cli, &auth);
1820 /* Marshall the outgoing data. */
1821 status = create_rpc_bind_req(state, cli,
1824 &cli->abstract_syntax,
1825 &cli->transfer_syntax,
1828 if (!NT_STATUS_IS_OK(status) &&
1829 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1833 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1834 DCERPC_PKT_BIND_ACK, state->rpc_call_id);
1835 if (subreq == NULL) {
1838 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1842 tevent_req_nterror(req, status);
1843 return tevent_req_post(req, ev);
1849 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1851 struct tevent_req *req = tevent_req_callback_data(
1852 subreq, struct tevent_req);
1853 struct rpc_pipe_bind_state *state = tevent_req_data(
1854 req, struct rpc_pipe_bind_state);
1855 struct pipe_auth_data *pauth = state->cli->auth;
1856 struct gensec_security *gensec_security;
1857 struct ncacn_packet *pkt = NULL;
1858 struct dcerpc_auth auth;
1859 DATA_BLOB auth_token = data_blob_null;
1862 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
1863 TALLOC_FREE(subreq);
1864 if (!NT_STATUS_IS_OK(status)) {
1865 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1866 rpccli_pipe_txt(talloc_tos(), state->cli),
1867 nt_errstr(status)));
1868 tevent_req_nterror(req, status);
1873 tevent_req_done(req);
1877 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1878 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1879 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1883 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1884 state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1886 switch(pauth->auth_type) {
1888 case DCERPC_AUTH_TYPE_NONE:
1889 /* Bind complete. */
1890 tevent_req_done(req);
1894 if (pkt->auth_length == 0) {
1895 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1899 /* get auth credentials */
1900 status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
1901 &pkt->u.bind_ack.auth_info,
1903 if (!NT_STATUS_IS_OK(status)) {
1904 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1905 nt_errstr(status)));
1906 tevent_req_nterror(req, status);
1910 if (auth.auth_type != pauth->auth_type) {
1911 DEBUG(0, (__location__ " Auth type %u mismatch expected %u.\n",
1912 auth.auth_type, pauth->auth_type));
1913 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1917 if (auth.auth_level != pauth->auth_level) {
1918 DEBUG(0, (__location__ " Auth level %u mismatch expected %u.\n",
1919 auth.auth_level, pauth->auth_level));
1920 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1924 if (auth.auth_context_id != pauth->auth_context_id) {
1925 DEBUG(0, (__location__ " Auth context id %u mismatch expected %u.\n",
1926 (unsigned)auth.auth_context_id,
1927 (unsigned)pauth->auth_context_id));
1928 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1936 * For authenticated binds we may need to do 3 or 4 leg binds.
1939 switch(pauth->auth_type) {
1941 case DCERPC_AUTH_TYPE_NONE:
1942 /* Bind complete. */
1943 tevent_req_done(req);
1947 gensec_security = pauth->auth_ctx;
1949 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1950 if (pauth->client_hdr_signing) {
1951 pauth->hdr_signing = true;
1952 gensec_want_feature(gensec_security,
1953 GENSEC_FEATURE_SIGN_PKT_HEADER);
1957 status = gensec_update(gensec_security, state,
1958 auth.credentials, &auth_token);
1959 if (NT_STATUS_EQUAL(status,
1960 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1961 status = rpc_bind_next_send(req, state,
1963 } else if (NT_STATUS_IS_OK(status)) {
1964 if (auth_token.length == 0) {
1965 /* Bind complete. */
1966 tevent_req_done(req);
1969 status = rpc_bind_finish_send(req, state,
1975 if (!NT_STATUS_IS_OK(status)) {
1976 tevent_req_nterror(req, status);
1981 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1982 struct rpc_pipe_bind_state *state,
1983 DATA_BLOB *auth_token)
1985 struct pipe_auth_data *auth = state->cli->auth;
1986 struct tevent_req *subreq;
1989 /* Now prepare the alter context pdu. */
1990 data_blob_free(&state->rpc_out);
1992 status = create_rpc_alter_context(state, auth,
1994 &state->cli->abstract_syntax,
1995 &state->cli->transfer_syntax,
1998 if (!NT_STATUS_IS_OK(status)) {
2002 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2003 &state->rpc_out, DCERPC_PKT_ALTER_RESP,
2004 state->rpc_call_id);
2005 if (subreq == NULL) {
2006 return NT_STATUS_NO_MEMORY;
2008 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2009 return NT_STATUS_OK;
2012 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
2013 struct rpc_pipe_bind_state *state,
2014 DATA_BLOB *auth_token)
2016 struct pipe_auth_data *auth = state->cli->auth;
2017 struct tevent_req *subreq;
2020 state->auth3 = true;
2022 /* Now prepare the auth3 context pdu. */
2023 data_blob_free(&state->rpc_out);
2025 status = create_rpc_bind_auth3(state, state->cli, auth,
2029 if (!NT_STATUS_IS_OK(status)) {
2033 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2034 &state->rpc_out, DCERPC_PKT_AUTH3,
2035 state->rpc_call_id);
2036 if (subreq == NULL) {
2037 return NT_STATUS_NO_MEMORY;
2039 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2040 return NT_STATUS_OK;
2043 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2045 return tevent_req_simple_recv_ntstatus(req);
2048 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2049 struct pipe_auth_data *auth)
2051 TALLOC_CTX *frame = talloc_stackframe();
2052 struct tevent_context *ev;
2053 struct tevent_req *req;
2054 NTSTATUS status = NT_STATUS_OK;
2056 ev = samba_tevent_context_init(frame);
2058 status = NT_STATUS_NO_MEMORY;
2062 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2064 status = NT_STATUS_NO_MEMORY;
2068 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2072 status = rpc_pipe_bind_recv(req);
2078 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2080 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2081 unsigned int timeout)
2085 if (rpc_cli->transport == NULL) {
2086 return RPCCLI_DEFAULT_TIMEOUT;
2089 if (rpc_cli->transport->set_timeout == NULL) {
2090 return RPCCLI_DEFAULT_TIMEOUT;
2093 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2095 return RPCCLI_DEFAULT_TIMEOUT;
2101 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2103 if (rpc_cli == NULL) {
2107 if (rpc_cli->transport == NULL) {
2111 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2114 struct rpccli_bh_state {
2115 struct rpc_pipe_client *rpc_cli;
2118 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2120 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2121 struct rpccli_bh_state);
2123 return rpccli_is_connected(hs->rpc_cli);
2126 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2129 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2130 struct rpccli_bh_state);
2132 return rpccli_set_timeout(hs->rpc_cli, timeout);
2135 static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
2136 enum dcerpc_AuthType *auth_type,
2137 enum dcerpc_AuthLevel *auth_level)
2139 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2140 struct rpccli_bh_state);
2142 if (hs->rpc_cli == NULL) {
2146 if (hs->rpc_cli->auth == NULL) {
2150 *auth_type = hs->rpc_cli->auth->auth_type;
2151 *auth_level = hs->rpc_cli->auth->auth_level;
2154 struct rpccli_bh_raw_call_state {
2160 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2162 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2163 struct tevent_context *ev,
2164 struct dcerpc_binding_handle *h,
2165 const struct GUID *object,
2168 const uint8_t *in_data,
2171 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2172 struct rpccli_bh_state);
2173 struct tevent_req *req;
2174 struct rpccli_bh_raw_call_state *state;
2176 struct tevent_req *subreq;
2178 req = tevent_req_create(mem_ctx, &state,
2179 struct rpccli_bh_raw_call_state);
2183 state->in_data.data = discard_const_p(uint8_t, in_data);
2184 state->in_data.length = in_length;
2186 ok = rpccli_bh_is_connected(h);
2188 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2189 return tevent_req_post(req, ev);
2192 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2193 opnum, &state->in_data);
2194 if (tevent_req_nomem(subreq, req)) {
2195 return tevent_req_post(req, ev);
2197 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2202 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2204 struct tevent_req *req =
2205 tevent_req_callback_data(subreq,
2207 struct rpccli_bh_raw_call_state *state =
2208 tevent_req_data(req,
2209 struct rpccli_bh_raw_call_state);
2212 state->out_flags = 0;
2214 /* TODO: support bigendian responses */
2216 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2217 TALLOC_FREE(subreq);
2218 if (!NT_STATUS_IS_OK(status)) {
2219 tevent_req_nterror(req, status);
2223 tevent_req_done(req);
2226 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2227 TALLOC_CTX *mem_ctx,
2230 uint32_t *out_flags)
2232 struct rpccli_bh_raw_call_state *state =
2233 tevent_req_data(req,
2234 struct rpccli_bh_raw_call_state);
2237 if (tevent_req_is_nterror(req, &status)) {
2238 tevent_req_received(req);
2242 *out_data = talloc_move(mem_ctx, &state->out_data.data);
2243 *out_length = state->out_data.length;
2244 *out_flags = state->out_flags;
2245 tevent_req_received(req);
2246 return NT_STATUS_OK;
2249 struct rpccli_bh_disconnect_state {
2253 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2254 struct tevent_context *ev,
2255 struct dcerpc_binding_handle *h)
2257 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2258 struct rpccli_bh_state);
2259 struct tevent_req *req;
2260 struct rpccli_bh_disconnect_state *state;
2263 req = tevent_req_create(mem_ctx, &state,
2264 struct rpccli_bh_disconnect_state);
2269 ok = rpccli_bh_is_connected(h);
2271 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2272 return tevent_req_post(req, ev);
2276 * TODO: do a real async disconnect ...
2278 * For now the caller needs to free rpc_cli
2282 tevent_req_done(req);
2283 return tevent_req_post(req, ev);
2286 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2290 if (tevent_req_is_nterror(req, &status)) {
2291 tevent_req_received(req);
2295 tevent_req_received(req);
2296 return NT_STATUS_OK;
2299 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2304 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2306 const void *_struct_ptr,
2307 const struct ndr_interface_call *call)
2309 void *struct_ptr = discard_const(_struct_ptr);
2311 if (DEBUGLEVEL < 10) {
2315 if (ndr_flags & NDR_IN) {
2316 ndr_print_function_debug(call->ndr_print,
2321 if (ndr_flags & NDR_OUT) {
2322 ndr_print_function_debug(call->ndr_print,
2329 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2331 .is_connected = rpccli_bh_is_connected,
2332 .set_timeout = rpccli_bh_set_timeout,
2333 .auth_info = rpccli_bh_auth_info,
2334 .raw_call_send = rpccli_bh_raw_call_send,
2335 .raw_call_recv = rpccli_bh_raw_call_recv,
2336 .disconnect_send = rpccli_bh_disconnect_send,
2337 .disconnect_recv = rpccli_bh_disconnect_recv,
2339 .ref_alloc = rpccli_bh_ref_alloc,
2340 .do_ndr_print = rpccli_bh_do_ndr_print,
2343 /* initialise a rpc_pipe_client binding handle */
2344 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2345 const struct GUID *object,
2346 const struct ndr_interface_table *table)
2348 struct dcerpc_binding_handle *h;
2349 struct rpccli_bh_state *hs;
2351 h = dcerpc_binding_handle_create(c,
2356 struct rpccli_bh_state,
2366 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2367 struct pipe_auth_data **presult)
2369 struct pipe_auth_data *result;
2370 struct auth_generic_state *auth_generic_ctx;
2373 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2374 if (result == NULL) {
2375 return NT_STATUS_NO_MEMORY;
2378 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2379 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2380 result->auth_context_id = 0;
2382 status = auth_generic_client_prepare(result,
2384 if (!NT_STATUS_IS_OK(status)) {
2385 DEBUG(1, ("Failed to create auth_generic context: %s\n",
2386 nt_errstr(status)));
2389 status = auth_generic_set_username(auth_generic_ctx, "");
2390 if (!NT_STATUS_IS_OK(status)) {
2391 DEBUG(1, ("Failed to set username: %s\n",
2392 nt_errstr(status)));
2395 status = auth_generic_set_domain(auth_generic_ctx, "");
2396 if (!NT_STATUS_IS_OK(status)) {
2397 DEBUG(1, ("Failed to set domain: %s\n",
2398 nt_errstr(status)));
2402 status = gensec_set_credentials(auth_generic_ctx->gensec_security,
2403 auth_generic_ctx->credentials);
2404 if (!NT_STATUS_IS_OK(status)) {
2405 DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
2406 nt_errstr(status)));
2409 talloc_unlink(auth_generic_ctx, auth_generic_ctx->credentials);
2410 auth_generic_ctx->credentials = NULL;
2412 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2413 talloc_free(auth_generic_ctx);
2415 return NT_STATUS_OK;
2418 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2419 enum dcerpc_AuthType auth_type,
2420 enum dcerpc_AuthLevel auth_level,
2422 const char *target_service,
2424 const char *username,
2425 const char *password,
2426 enum credentials_use_kerberos use_kerberos,
2427 struct netlogon_creds_CredentialState *creds,
2428 struct pipe_auth_data **presult)
2430 struct auth_generic_state *auth_generic_ctx;
2431 struct pipe_auth_data *result;
2434 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2435 if (result == NULL) {
2436 return NT_STATUS_NO_MEMORY;
2439 result->auth_type = auth_type;
2440 result->auth_level = auth_level;
2441 result->auth_context_id = 1;
2443 status = auth_generic_client_prepare(result,
2445 if (!NT_STATUS_IS_OK(status)) {
2449 status = auth_generic_set_username(auth_generic_ctx, username);
2450 if (!NT_STATUS_IS_OK(status)) {
2454 status = auth_generic_set_domain(auth_generic_ctx, domain);
2455 if (!NT_STATUS_IS_OK(status)) {
2459 status = auth_generic_set_password(auth_generic_ctx, password);
2460 if (!NT_STATUS_IS_OK(status)) {
2464 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2465 if (!NT_STATUS_IS_OK(status)) {
2469 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2470 if (!NT_STATUS_IS_OK(status)) {
2474 cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos);
2475 cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
2477 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2478 if (!NT_STATUS_IS_OK(status)) {
2482 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2483 talloc_free(auth_generic_ctx);
2485 return NT_STATUS_OK;
2488 TALLOC_FREE(result);
2492 /* This routine steals the creds pointer that is passed in */
2493 static NTSTATUS rpccli_generic_bind_data_from_creds(TALLOC_CTX *mem_ctx,
2494 enum dcerpc_AuthType auth_type,
2495 enum dcerpc_AuthLevel auth_level,
2497 const char *target_service,
2498 struct cli_credentials *creds,
2499 struct pipe_auth_data **presult)
2501 struct auth_generic_state *auth_generic_ctx;
2502 struct pipe_auth_data *result;
2505 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2506 if (result == NULL) {
2507 return NT_STATUS_NO_MEMORY;
2510 result->auth_type = auth_type;
2511 result->auth_level = auth_level;
2512 result->auth_context_id = 1;
2514 status = auth_generic_client_prepare(result,
2516 if (!NT_STATUS_IS_OK(status)) {
2520 status = auth_generic_set_creds(auth_generic_ctx, creds);
2521 if (!NT_STATUS_IS_OK(status)) {
2525 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2526 if (!NT_STATUS_IS_OK(status)) {
2530 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2531 if (!NT_STATUS_IS_OK(status)) {
2535 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2536 if (!NT_STATUS_IS_OK(status)) {
2540 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2541 talloc_free(auth_generic_ctx);
2543 return NT_STATUS_OK;
2546 TALLOC_FREE(result);
2550 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2551 struct pipe_auth_data **presult)
2553 return rpccli_generic_bind_data(mem_ctx,
2554 DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
2555 DCERPC_AUTH_LEVEL_CONNECT,
2557 "host", /* target_service */
2558 NAME_NT_AUTHORITY, /* domain */
2561 CRED_DONT_USE_KERBEROS,
2562 NULL, /* netlogon_creds_CredentialState */
2567 * Create an rpc pipe client struct, connecting to a tcp port.
2569 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2570 const struct sockaddr_storage *ss_addr,
2572 const struct ndr_interface_table *table,
2573 struct rpc_pipe_client **presult)
2575 struct rpc_pipe_client *result;
2576 struct sockaddr_storage addr;
2580 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2581 if (result == NULL) {
2582 return NT_STATUS_NO_MEMORY;
2585 result->abstract_syntax = table->syntax_id;
2586 result->transfer_syntax = ndr_transfer_syntax_ndr;
2588 result->desthost = talloc_strdup(result, host);
2589 result->srv_name_slash = talloc_asprintf_strupper_m(
2590 result, "\\\\%s", result->desthost);
2591 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2592 status = NT_STATUS_NO_MEMORY;
2596 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2597 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2599 if (ss_addr == NULL) {
2600 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2601 status = NT_STATUS_NOT_FOUND;
2608 status = open_socket_out(&addr, port, 60*1000, &fd);
2609 if (!NT_STATUS_IS_OK(status)) {
2612 set_socket_options(fd, lp_socket_options());
2614 status = rpc_transport_sock_init(result, fd, &result->transport);
2615 if (!NT_STATUS_IS_OK(status)) {
2620 result->transport->transport = NCACN_IP_TCP;
2622 result->binding_handle = rpccli_bh_create(result, NULL, table);
2623 if (result->binding_handle == NULL) {
2624 TALLOC_FREE(result);
2625 return NT_STATUS_NO_MEMORY;
2629 return NT_STATUS_OK;
2632 TALLOC_FREE(result);
2637 * Determine the tcp port on which a dcerpc interface is listening
2638 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2641 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2642 const struct sockaddr_storage *addr,
2643 const struct ndr_interface_table *table,
2647 struct rpc_pipe_client *epm_pipe = NULL;
2648 struct dcerpc_binding_handle *epm_handle = NULL;
2649 struct pipe_auth_data *auth = NULL;
2650 struct dcerpc_binding *map_binding = NULL;
2651 struct dcerpc_binding *res_binding = NULL;
2652 enum dcerpc_transport_t transport;
2653 const char *endpoint = NULL;
2654 struct epm_twr_t *map_tower = NULL;
2655 struct epm_twr_t *res_towers = NULL;
2656 struct policy_handle *entry_handle = NULL;
2657 uint32_t num_towers = 0;
2658 uint32_t max_towers = 1;
2659 struct epm_twr_p_t towers;
2660 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2661 uint32_t result = 0;
2663 if (pport == NULL) {
2664 status = NT_STATUS_INVALID_PARAMETER;
2668 if (ndr_syntax_id_equal(&table->syntax_id,
2669 &ndr_table_epmapper.syntax_id)) {
2671 status = NT_STATUS_OK;
2675 /* open the connection to the endpoint mapper */
2676 status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2677 &ndr_table_epmapper,
2680 if (!NT_STATUS_IS_OK(status)) {
2683 epm_handle = epm_pipe->binding_handle;
2685 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2686 if (!NT_STATUS_IS_OK(status)) {
2690 status = rpc_pipe_bind(epm_pipe, auth);
2691 if (!NT_STATUS_IS_OK(status)) {
2695 /* create tower for asking the epmapper */
2697 status = dcerpc_parse_binding(tmp_ctx, "ncacn_ip_tcp:[135]",
2699 if (!NT_STATUS_IS_OK(status)) {
2703 status = dcerpc_binding_set_abstract_syntax(map_binding,
2705 if (!NT_STATUS_IS_OK(status)) {
2709 map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
2710 if (map_tower == NULL) {
2711 status = NT_STATUS_NO_MEMORY;
2715 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2716 &(map_tower->tower));
2717 if (!NT_STATUS_IS_OK(status)) {
2721 /* allocate further parameters for the epm_Map call */
2723 res_towers = talloc_array(tmp_ctx, struct epm_twr_t, max_towers);
2724 if (res_towers == NULL) {
2725 status = NT_STATUS_NO_MEMORY;
2728 towers.twr = res_towers;
2730 entry_handle = talloc_zero(tmp_ctx, struct policy_handle);
2731 if (entry_handle == NULL) {
2732 status = NT_STATUS_NO_MEMORY;
2736 /* ask the endpoint mapper for the port */
2738 status = dcerpc_epm_Map(epm_handle,
2740 discard_const_p(struct GUID,
2741 &(table->syntax_id.uuid)),
2749 if (!NT_STATUS_IS_OK(status)) {
2753 if (result != EPMAPPER_STATUS_OK) {
2754 status = NT_STATUS_UNSUCCESSFUL;
2758 if (num_towers != 1) {
2759 status = NT_STATUS_UNSUCCESSFUL;
2763 /* extract the port from the answer */
2765 status = dcerpc_binding_from_tower(tmp_ctx,
2766 &(towers.twr->tower),
2768 if (!NT_STATUS_IS_OK(status)) {
2772 transport = dcerpc_binding_get_transport(res_binding);
2773 endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
2775 /* are further checks here necessary? */
2776 if (transport != NCACN_IP_TCP) {
2777 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2781 if (endpoint == NULL) {
2782 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2786 *pport = (uint16_t)atoi(endpoint);
2789 TALLOC_FREE(tmp_ctx);
2794 * Create a rpc pipe client struct, connecting to a host via tcp.
2795 * The port is determined by asking the endpoint mapper on the given
2798 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2799 const struct sockaddr_storage *addr,
2800 const struct ndr_interface_table *table,
2801 struct rpc_pipe_client **presult)
2806 status = rpc_pipe_get_tcp_port(host, addr, table, &port);
2807 if (!NT_STATUS_IS_OK(status)) {
2811 return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2815 /********************************************************************
2816 Create a rpc pipe client struct, connecting to a unix domain socket
2817 ********************************************************************/
2818 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2819 const struct ndr_interface_table *table,
2820 struct rpc_pipe_client **presult)
2822 struct rpc_pipe_client *result;
2823 struct sockaddr_un addr;
2828 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2829 if (result == NULL) {
2830 return NT_STATUS_NO_MEMORY;
2833 result->abstract_syntax = table->syntax_id;
2834 result->transfer_syntax = ndr_transfer_syntax_ndr;
2836 result->desthost = get_myname(result);
2837 result->srv_name_slash = talloc_asprintf_strupper_m(
2838 result, "\\\\%s", result->desthost);
2839 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2840 status = NT_STATUS_NO_MEMORY;
2844 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2845 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2847 fd = socket(AF_UNIX, SOCK_STREAM, 0);
2849 status = map_nt_error_from_unix(errno);
2854 addr.sun_family = AF_UNIX;
2855 strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2856 salen = sizeof(struct sockaddr_un);
2858 if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
2859 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2862 return map_nt_error_from_unix(errno);
2865 status = rpc_transport_sock_init(result, fd, &result->transport);
2866 if (!NT_STATUS_IS_OK(status)) {
2871 result->transport->transport = NCALRPC;
2873 result->binding_handle = rpccli_bh_create(result, NULL, table);
2874 if (result->binding_handle == NULL) {
2875 TALLOC_FREE(result);
2876 return NT_STATUS_NO_MEMORY;
2880 return NT_STATUS_OK;
2883 TALLOC_FREE(result);
2887 struct rpc_pipe_client_np_ref {
2888 struct cli_state *cli;
2889 struct rpc_pipe_client *pipe;
2892 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2894 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2898 /****************************************************************************
2899 Open a named pipe over SMB to a remote server.
2901 * CAVEAT CALLER OF THIS FUNCTION:
2902 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2903 * so be sure that this function is called AFTER any structure (vs pointer)
2904 * assignment of the cli. In particular, libsmbclient does structure
2905 * assignments of cli, which invalidates the data in the returned
2906 * rpc_pipe_client if this function is called before the structure assignment
2909 ****************************************************************************/
2911 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2912 const struct ndr_interface_table *table,
2913 struct rpc_pipe_client **presult)
2915 struct rpc_pipe_client *result;
2917 struct rpc_pipe_client_np_ref *np_ref;
2919 /* sanity check to protect against crashes */
2922 return NT_STATUS_INVALID_HANDLE;
2925 result = talloc_zero(NULL, struct rpc_pipe_client);
2926 if (result == NULL) {
2927 return NT_STATUS_NO_MEMORY;
2930 result->abstract_syntax = table->syntax_id;
2931 result->transfer_syntax = ndr_transfer_syntax_ndr;
2932 result->desthost = talloc_strdup(result, smbXcli_conn_remote_name(cli->conn));
2933 result->srv_name_slash = talloc_asprintf_strupper_m(
2934 result, "\\\\%s", result->desthost);
2936 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2937 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2939 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2940 TALLOC_FREE(result);
2941 return NT_STATUS_NO_MEMORY;
2944 status = rpc_transport_np_init(result, cli, table,
2945 &result->transport);
2946 if (!NT_STATUS_IS_OK(status)) {
2947 TALLOC_FREE(result);
2951 result->transport->transport = NCACN_NP;
2953 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
2954 if (np_ref == NULL) {
2955 TALLOC_FREE(result);
2956 return NT_STATUS_NO_MEMORY;
2959 np_ref->pipe = result;
2961 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
2962 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
2964 result->binding_handle = rpccli_bh_create(result, NULL, table);
2965 if (result->binding_handle == NULL) {
2966 TALLOC_FREE(result);
2967 return NT_STATUS_NO_MEMORY;
2971 return NT_STATUS_OK;
2974 /****************************************************************************
2975 Open a pipe to a remote server.
2976 ****************************************************************************/
2978 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2979 enum dcerpc_transport_t transport,
2980 const struct ndr_interface_table *table,
2981 struct rpc_pipe_client **presult)
2983 switch (transport) {
2985 return rpc_pipe_open_tcp(NULL,
2986 smbXcli_conn_remote_name(cli->conn),
2987 smbXcli_conn_remote_sockaddr(cli->conn),
2990 return rpc_pipe_open_np(cli, table, presult);
2992 return NT_STATUS_NOT_IMPLEMENTED;
2996 /****************************************************************************
2997 Open a named pipe to an SMB server and bind anonymously.
2998 ****************************************************************************/
3000 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3001 enum dcerpc_transport_t transport,
3002 const struct ndr_interface_table *table,
3003 struct rpc_pipe_client **presult)
3005 struct rpc_pipe_client *result;
3006 struct pipe_auth_data *auth;
3009 status = cli_rpc_pipe_open(cli, transport, table, &result);
3010 if (!NT_STATUS_IS_OK(status)) {
3014 status = rpccli_anon_bind_data(result, &auth);
3015 if (!NT_STATUS_IS_OK(status)) {
3016 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3017 nt_errstr(status)));
3018 TALLOC_FREE(result);
3023 * This is a bit of an abstraction violation due to the fact that an
3024 * anonymous bind on an authenticated SMB inherits the user/domain
3025 * from the enclosing SMB creds
3028 if (transport == NCACN_NP) {
3029 struct smbXcli_session *session;
3031 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3032 session = cli->smb2.session;
3034 session = cli->smb1.session;
3037 status = smbXcli_session_application_key(session, auth,
3038 &auth->transport_session_key);
3039 if (!NT_STATUS_IS_OK(status)) {
3040 auth->transport_session_key = data_blob_null;
3044 status = rpc_pipe_bind(result, auth);
3045 if (!NT_STATUS_IS_OK(status)) {
3047 if (ndr_syntax_id_equal(&table->syntax_id,
3048 &ndr_table_dssetup.syntax_id)) {
3049 /* non AD domains just don't have this pipe, avoid
3050 * level 0 statement in that case - gd */
3053 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3054 "%s failed with error %s\n",
3056 nt_errstr(status) ));
3057 TALLOC_FREE(result);
3061 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3062 "%s and bound anonymously.\n",
3067 return NT_STATUS_OK;
3070 /****************************************************************************
3071 ****************************************************************************/
3073 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3074 const struct ndr_interface_table *table,
3075 struct rpc_pipe_client **presult)
3077 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3081 /****************************************************************************
3082 Open a named pipe to an SMB server and bind using the mech specified
3084 This routine references the creds pointer that is passed in
3085 ****************************************************************************/
3087 NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
3088 const struct ndr_interface_table *table,
3089 enum dcerpc_transport_t transport,
3090 enum dcerpc_AuthType auth_type,
3091 enum dcerpc_AuthLevel auth_level,
3093 struct cli_credentials *creds,
3094 struct rpc_pipe_client **presult)
3096 struct rpc_pipe_client *result;
3097 struct pipe_auth_data *auth = NULL;
3098 const char *target_service = table->authservices->names[0];
3102 status = cli_rpc_pipe_open(cli, transport, table, &result);
3103 if (!NT_STATUS_IS_OK(status)) {
3107 status = rpccli_generic_bind_data_from_creds(result,
3108 auth_type, auth_level,
3109 server, target_service,
3112 if (!NT_STATUS_IS_OK(status)) {
3113 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3114 nt_errstr(status)));
3118 status = rpc_pipe_bind(result, auth);
3119 if (!NT_STATUS_IS_OK(status)) {
3120 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
3121 nt_errstr(status) ));
3125 DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
3126 "machine %s and bound as user %s.\n", table->name,
3127 result->desthost, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3130 return NT_STATUS_OK;
3134 TALLOC_FREE(result);
3138 /****************************************************************************
3139 Open a named pipe to an SMB server and bind using the mech specified
3141 This routine steals the creds pointer that is passed in
3142 ****************************************************************************/
3144 NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
3145 const struct ndr_interface_table *table,
3146 enum dcerpc_transport_t transport,
3147 enum credentials_use_kerberos use_kerberos,
3148 enum dcerpc_AuthType auth_type,
3149 enum dcerpc_AuthLevel auth_level,
3152 const char *username,
3153 const char *password,
3154 struct rpc_pipe_client **presult)
3156 struct rpc_pipe_client *result;
3157 struct pipe_auth_data *auth = NULL;
3158 const char *target_service = table->authservices->names[0];
3162 status = cli_rpc_pipe_open(cli, transport, table, &result);
3163 if (!NT_STATUS_IS_OK(status)) {
3167 status = rpccli_generic_bind_data(result,
3168 auth_type, auth_level,
3169 server, target_service,
3170 domain, username, password,
3171 CRED_AUTO_USE_KERBEROS,
3174 if (!NT_STATUS_IS_OK(status)) {
3175 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3176 nt_errstr(status)));
3180 status = rpc_pipe_bind(result, auth);
3181 if (!NT_STATUS_IS_OK(status)) {
3182 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
3183 nt_errstr(status) ));
3187 DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
3188 "machine %s and bound as user %s\\%s.\n", table->name,
3189 result->desthost, domain, username));
3192 return NT_STATUS_OK;
3196 TALLOC_FREE(result);
3200 NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
3201 const struct ndr_interface_table *table,
3202 enum dcerpc_transport_t transport,
3203 struct cli_credentials *cli_creds,
3204 struct netlogon_creds_cli_context *netlogon_creds,
3205 struct rpc_pipe_client **_rpccli)
3207 struct rpc_pipe_client *rpccli;
3208 struct pipe_auth_data *rpcauth;
3209 const char *target_service = table->authservices->names[0];
3210 struct netlogon_creds_CredentialState *ncreds = NULL;
3211 enum dcerpc_AuthLevel auth_level;
3213 int rpc_pipe_bind_dbglvl = 0;
3215 status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
3216 if (!NT_STATUS_IS_OK(status)) {
3220 status = netlogon_creds_cli_lock(netlogon_creds, rpccli, &ncreds);
3221 if (!NT_STATUS_IS_OK(status)) {
3222 DEBUG(0, ("netlogon_creds_cli_get returned %s\n",
3223 nt_errstr(status)));
3224 TALLOC_FREE(rpccli);
3228 auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
3230 cli_credentials_set_netlogon_creds(cli_creds, ncreds);
3232 status = rpccli_generic_bind_data_from_creds(rpccli,
3233 DCERPC_AUTH_TYPE_SCHANNEL,
3239 if (!NT_STATUS_IS_OK(status)) {
3240 DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
3241 nt_errstr(status)));
3242 TALLOC_FREE(rpccli);
3246 status = rpc_pipe_bind(rpccli, rpcauth);
3247 cli_credentials_set_netlogon_creds(cli_creds, NULL);
3248 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3249 rpc_pipe_bind_dbglvl = 1;
3250 netlogon_creds_cli_delete(netlogon_creds, &ncreds);
3252 if (!NT_STATUS_IS_OK(status)) {
3253 DEBUG(rpc_pipe_bind_dbglvl,
3254 ("%s: rpc_pipe_bind failed with error %s\n",
3255 __func__, nt_errstr(status)));
3256 TALLOC_FREE(rpccli);
3260 TALLOC_FREE(ncreds);
3262 if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) {
3266 status = netlogon_creds_cli_check(netlogon_creds,
3267 rpccli->binding_handle);
3268 if (!NT_STATUS_IS_OK(status)) {
3269 DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
3270 nt_errstr(status)));
3271 TALLOC_FREE(rpccli);
3277 DEBUG(10,("%s: opened pipe %s to machine %s "
3278 "for domain %s and bound using schannel.\n",
3279 __func__, table->name,
3280 rpccli->desthost, cli_credentials_get_domain(cli_creds)));
3283 return NT_STATUS_OK;
3286 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3287 struct rpc_pipe_client *cli,
3288 DATA_BLOB *session_key)
3291 struct pipe_auth_data *a;
3292 struct gensec_security *gensec_security;
3293 DATA_BLOB sk = data_blob_null;
3294 bool make_dup = false;
3296 if (!session_key || !cli) {
3297 return NT_STATUS_INVALID_PARAMETER;
3303 return NT_STATUS_INVALID_PARAMETER;
3306 switch (cli->auth->auth_type) {
3307 case DCERPC_AUTH_TYPE_NONE:
3308 sk = data_blob_const(a->transport_session_key.data,
3309 a->transport_session_key.length);
3313 gensec_security = a->auth_ctx;
3314 status = gensec_session_key(gensec_security, mem_ctx, &sk);
3315 if (!NT_STATUS_IS_OK(status)) {
3323 return NT_STATUS_NO_USER_SESSION_KEY;
3327 *session_key = data_blob_dup_talloc(mem_ctx, sk);
3332 return NT_STATUS_OK;