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 "libsmb/namequery.h"
24 #include "../lib/util/tevent_ntstatus.h"
25 #include "librpc/gen_ndr/ndr_epmapper_c.h"
26 #include "../librpc/gen_ndr/ndr_dssetup.h"
27 #include "../libcli/auth/schannel.h"
28 #include "../libcli/auth/netlogon_creds_cli.h"
29 #include "auth_generic.h"
30 #include "librpc/gen_ndr/ndr_dcerpc.h"
31 #include "librpc/gen_ndr/ndr_netlogon_c.h"
32 #include "librpc/gen_ndr/auth.h"
33 #include "librpc/rpc/dcerpc.h"
34 #include "librpc/rpc/dcerpc_util.h"
37 #include "libsmb/libsmb.h"
38 #include "auth/gensec/gensec.h"
39 #include "auth/credentials/credentials.h"
40 #include "auth/auth_util.h"
41 #include "../libcli/smb/smbXcli_base.h"
42 #include "lib/tsocket/tsocket.h"
43 #include "libcli/named_pipe_auth/npa_tstream.h"
44 #include "librpc/gen_ndr/ndr_winreg.h"
48 #define DBGC_CLASS DBGC_RPC_CLI
50 /********************************************************************
51 Pipe description for a DEBUG
52 ********************************************************************/
53 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
54 struct rpc_pipe_client *cli)
56 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
63 /********************************************************************
65 ********************************************************************/
67 static uint32_t get_rpc_call_id(void)
69 static uint32_t call_id = 0;
73 /*******************************************************************
74 Use SMBreadX to get rest of one fragment's worth of rpc data.
75 Reads the whole size or give an error message
76 ********************************************************************/
78 struct rpc_read_state {
79 struct tevent_context *ev;
80 struct rpc_cli_transport *transport;
86 static void rpc_read_done(struct tevent_req *subreq);
88 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
89 struct tevent_context *ev,
90 struct rpc_cli_transport *transport,
91 uint8_t *data, size_t size)
93 struct tevent_req *req, *subreq;
94 struct rpc_read_state *state;
96 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
101 state->transport = transport;
106 DBG_INFO("data_to_read: %zu\n", size);
108 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
110 if (subreq == NULL) {
113 tevent_req_set_callback(subreq, rpc_read_done, req);
121 static void rpc_read_done(struct tevent_req *subreq)
123 struct tevent_req *req = tevent_req_callback_data(
124 subreq, struct tevent_req);
125 struct rpc_read_state *state = tevent_req_data(
126 req, struct rpc_read_state);
130 status = state->transport->read_recv(subreq, &received);
132 if (tevent_req_nterror(req, status)) {
136 state->num_read += received;
137 if (state->num_read == state->size) {
138 tevent_req_done(req);
142 subreq = state->transport->read_send(state, state->ev,
143 state->data + state->num_read,
144 state->size - state->num_read,
145 state->transport->priv);
146 if (tevent_req_nomem(subreq, req)) {
149 tevent_req_set_callback(subreq, rpc_read_done, req);
152 static NTSTATUS rpc_read_recv(struct tevent_req *req)
154 return tevent_req_simple_recv_ntstatus(req);
157 struct rpc_write_state {
158 struct tevent_context *ev;
159 struct rpc_cli_transport *transport;
165 static void rpc_write_done(struct tevent_req *subreq);
167 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
168 struct tevent_context *ev,
169 struct rpc_cli_transport *transport,
170 const uint8_t *data, size_t size)
172 struct tevent_req *req, *subreq;
173 struct rpc_write_state *state;
175 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
180 state->transport = transport;
183 state->num_written = 0;
185 DBG_INFO("data_to_write: %zu\n", size);
187 subreq = transport->write_send(state, ev, data, size, transport->priv);
188 if (tevent_req_nomem(subreq, req)) {
189 return tevent_req_post(req, ev);
191 tevent_req_set_callback(subreq, rpc_write_done, req);
195 static void rpc_write_done(struct tevent_req *subreq)
197 struct tevent_req *req = tevent_req_callback_data(
198 subreq, struct tevent_req);
199 struct rpc_write_state *state = tevent_req_data(
200 req, struct rpc_write_state);
204 status = state->transport->write_recv(subreq, &written);
206 if (tevent_req_nterror(req, status)) {
210 state->num_written += written;
212 if (state->num_written == state->size) {
213 tevent_req_done(req);
217 subreq = state->transport->write_send(state, state->ev,
218 state->data + state->num_written,
219 state->size - state->num_written,
220 state->transport->priv);
221 if (tevent_req_nomem(subreq, req)) {
224 tevent_req_set_callback(subreq, rpc_write_done, req);
227 static NTSTATUS rpc_write_recv(struct tevent_req *req)
229 return tevent_req_simple_recv_ntstatus(req);
233 /****************************************************************************
234 Try and get a PDU's worth of data from current_pdu. If not, then read more
236 ****************************************************************************/
238 struct get_complete_frag_state {
239 struct tevent_context *ev;
240 struct rpc_pipe_client *cli;
245 static void get_complete_frag_got_header(struct tevent_req *subreq);
246 static void get_complete_frag_got_rest(struct tevent_req *subreq);
248 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
249 struct tevent_context *ev,
250 struct rpc_pipe_client *cli,
253 struct tevent_req *req, *subreq;
254 struct get_complete_frag_state *state;
257 req = tevent_req_create(mem_ctx, &state,
258 struct get_complete_frag_state);
264 state->frag_len = RPC_HEADER_LEN;
267 received = pdu->length;
268 if (received < RPC_HEADER_LEN) {
269 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
271 return tevent_req_post(req, ev);
273 subreq = rpc_read_send(state, state->ev,
274 state->cli->transport,
275 pdu->data + received,
276 RPC_HEADER_LEN - received);
277 if (tevent_req_nomem(subreq, req)) {
278 return tevent_req_post(req, ev);
280 tevent_req_set_callback(subreq, get_complete_frag_got_header,
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);
291 if (received >= state->frag_len) {
293 * Got the whole fragment
295 tevent_req_done(req);
296 return tevent_req_post(req, ev);
299 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
301 return tevent_req_post(req, ev);
304 subreq = rpc_read_send(
307 state->cli->transport,
308 pdu->data + received,
309 state->frag_len - received);
310 if (tevent_req_nomem(subreq, req)) {
311 return tevent_req_post(req, ev);
313 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
317 static void get_complete_frag_got_header(struct tevent_req *subreq)
319 struct tevent_req *req = tevent_req_callback_data(
320 subreq, struct tevent_req);
321 struct get_complete_frag_state *state = tevent_req_data(
322 req, struct get_complete_frag_state);
325 status = rpc_read_recv(subreq);
327 if (tevent_req_nterror(req, status)) {
331 state->frag_len = dcerpc_get_frag_length(state->pdu);
332 if (state->frag_len < RPC_HEADER_LEN) {
333 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
337 if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
343 * We're here in this piece of code because we've read exactly
344 * RPC_HEADER_LEN bytes into state->pdu.
347 subreq = rpc_read_send(state, state->ev, state->cli->transport,
348 state->pdu->data + RPC_HEADER_LEN,
349 state->frag_len - RPC_HEADER_LEN);
350 if (tevent_req_nomem(subreq, req)) {
353 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
356 static void get_complete_frag_got_rest(struct tevent_req *subreq)
358 NTSTATUS status = rpc_read_recv(subreq);
359 return tevent_req_simple_finish_ntstatus(subreq, status);
362 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
364 return tevent_req_simple_recv_ntstatus(req);
367 /****************************************************************************
368 Do basic authentication checks on an incoming pdu.
369 ****************************************************************************/
371 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
372 struct rpc_pipe_client *cli,
373 struct ncacn_packet *pkt,
375 uint8_t expected_pkt_type,
378 DATA_BLOB *reply_pdu)
380 const struct dcerpc_response *r = NULL;
381 DATA_BLOB tmp_stub = { .data = NULL };
385 * Point the return values at the real data including the RPC
386 * header. Just in case the caller wants it.
390 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
391 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
393 * TODO: do we still need this hack which was introduced
394 * in commit a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0.
396 * I don't even know what AS/U might be...
398 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
399 "fragment first/last ON.\n"));
400 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
403 /* Ensure we have the correct type. */
404 switch (pkt->ptype) {
405 case DCERPC_PKT_BIND_NAK:
406 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
407 rpccli_pipe_txt(talloc_tos(), cli)));
409 ret = dcerpc_verify_ncacn_packet_header(pkt,
411 0, /* max_auth_info */
412 DCERPC_PFC_FLAG_FIRST |
413 DCERPC_PFC_FLAG_LAST,
414 0); /* optional flags */
415 if (!NT_STATUS_IS_OK(ret)) {
416 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
417 "RPC packet type - %u, expected %u: %s\n",
418 rpccli_pipe_txt(talloc_tos(), cli),
419 pkt->ptype, expected_pkt_type,
421 NDR_PRINT_DEBUG(ncacn_packet, pkt);
425 /* Use this for now... */
426 return NT_STATUS_NETWORK_ACCESS_DENIED;
428 case DCERPC_PKT_BIND_ACK:
429 ret = dcerpc_verify_ncacn_packet_header(pkt,
431 pkt->u.bind_ack.auth_info.length,
432 DCERPC_PFC_FLAG_FIRST |
433 DCERPC_PFC_FLAG_LAST,
434 DCERPC_PFC_FLAG_CONC_MPX |
435 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
436 if (!NT_STATUS_IS_OK(ret)) {
437 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
438 "RPC packet type - %u, expected %u: %s\n",
439 rpccli_pipe_txt(talloc_tos(), cli),
440 pkt->ptype, expected_pkt_type,
442 NDR_PRINT_DEBUG(ncacn_packet, pkt);
448 case DCERPC_PKT_ALTER_RESP:
449 ret = dcerpc_verify_ncacn_packet_header(pkt,
451 pkt->u.alter_resp.auth_info.length,
452 DCERPC_PFC_FLAG_FIRST |
453 DCERPC_PFC_FLAG_LAST,
454 DCERPC_PFC_FLAG_CONC_MPX |
455 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
456 if (!NT_STATUS_IS_OK(ret)) {
457 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
458 "RPC packet type - %u, expected %u: %s\n",
459 rpccli_pipe_txt(talloc_tos(), cli),
460 pkt->ptype, expected_pkt_type,
462 NDR_PRINT_DEBUG(ncacn_packet, pkt);
468 case DCERPC_PKT_RESPONSE:
470 r = &pkt->u.response;
472 ret = dcerpc_verify_ncacn_packet_header(pkt,
474 r->stub_and_verifier.length,
475 0, /* required_flags */
476 DCERPC_PFC_FLAG_FIRST |
477 DCERPC_PFC_FLAG_LAST);
478 if (!NT_STATUS_IS_OK(ret)) {
479 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
480 "RPC packet type - %u, expected %u: %s\n",
481 rpccli_pipe_txt(talloc_tos(), cli),
482 pkt->ptype, expected_pkt_type,
484 NDR_PRINT_DEBUG(ncacn_packet, pkt);
488 tmp_stub.data = r->stub_and_verifier.data;
489 tmp_stub.length = r->stub_and_verifier.length;
491 /* Here's where we deal with incoming sign/seal. */
492 ret = dcerpc_check_auth(cli->auth, pkt,
494 DCERPC_RESPONSE_LENGTH,
496 if (!NT_STATUS_IS_OK(ret)) {
497 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
498 "RPC packet type - %u, expected %u: %s\n",
499 rpccli_pipe_txt(talloc_tos(), cli),
500 pkt->ptype, expected_pkt_type,
502 NDR_PRINT_DEBUG(ncacn_packet, pkt);
506 /* Point the return values at the NDR data. */
509 DEBUG(10, ("Got pdu len %lu, data_len %lu\n",
510 (long unsigned int)pdu->length,
511 (long unsigned int)rdata->length));
514 * If this is the first reply, and the allocation hint is
515 * reasonable, try and set up the reply_pdu DATA_BLOB to the
519 if ((reply_pdu->length == 0) &&
520 r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
521 if (!data_blob_realloc(mem_ctx, reply_pdu,
523 DEBUG(0, ("reply alloc hint %d too "
524 "large to allocate\n",
525 (int)r->alloc_hint));
526 return NT_STATUS_NO_MEMORY;
532 case DCERPC_PKT_FAULT:
534 ret = dcerpc_verify_ncacn_packet_header(pkt,
536 0, /* max_auth_info */
537 DCERPC_PFC_FLAG_FIRST |
538 DCERPC_PFC_FLAG_LAST,
539 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
540 if (!NT_STATUS_IS_OK(ret)) {
541 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
542 "RPC packet type - %u, expected %u: %s\n",
543 rpccli_pipe_txt(talloc_tos(), cli),
544 pkt->ptype, expected_pkt_type,
546 NDR_PRINT_DEBUG(ncacn_packet, pkt);
550 DEBUG(1, (__location__ ": RPC fault code %s received "
552 dcerpc_errstr(talloc_tos(),
553 pkt->u.fault.status),
554 rpccli_pipe_txt(talloc_tos(), cli)));
556 return dcerpc_fault_to_nt_status(pkt->u.fault.status);
559 DEBUG(0, (__location__ "Unknown packet type %u received "
561 (unsigned int)pkt->ptype,
562 rpccli_pipe_txt(talloc_tos(), cli)));
563 return NT_STATUS_RPC_PROTOCOL_ERROR;
567 if (pkt->call_id != call_id) {
568 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
569 "RPC call_id - %u, not %u\n",
570 rpccli_pipe_txt(talloc_tos(), cli),
571 pkt->call_id, call_id));
572 return NT_STATUS_RPC_PROTOCOL_ERROR;
578 /****************************************************************************
579 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
580 ****************************************************************************/
582 struct cli_api_pipe_state {
583 struct tevent_context *ev;
584 struct rpc_cli_transport *transport;
589 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
590 static void cli_api_pipe_write_done(struct tevent_req *subreq);
591 static void cli_api_pipe_read_done(struct tevent_req *subreq);
593 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
594 struct tevent_context *ev,
595 struct rpc_cli_transport *transport,
596 uint8_t *data, size_t data_len,
597 uint32_t max_rdata_len)
599 struct tevent_req *req, *subreq;
600 struct cli_api_pipe_state *state;
602 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
607 state->transport = transport;
609 if (max_rdata_len < RPC_HEADER_LEN) {
611 * For a RPC reply we always need at least RPC_HEADER_LEN
612 * bytes. We check this here because we will receive
613 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
615 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
616 return tevent_req_post(req, ev);
619 if (transport->trans_send != NULL) {
620 subreq = transport->trans_send(state, ev, data, data_len,
621 max_rdata_len, transport->priv);
622 if (tevent_req_nomem(subreq, req)) {
623 return tevent_req_post(req, ev);
625 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
630 * If the transport does not provide a "trans" routine, i.e. for
631 * example the ncacn_ip_tcp transport, do the write/read step here.
634 subreq = rpc_write_send(state, ev, transport, data, data_len);
635 if (tevent_req_nomem(subreq, req)) {
636 return tevent_req_post(req, ev);
638 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
642 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
644 struct tevent_req *req = tevent_req_callback_data(
645 subreq, struct tevent_req);
646 struct cli_api_pipe_state *state = tevent_req_data(
647 req, struct cli_api_pipe_state);
650 status = state->transport->trans_recv(subreq, state, &state->rdata,
653 if (tevent_req_nterror(req, status)) {
656 tevent_req_done(req);
659 static void cli_api_pipe_write_done(struct tevent_req *subreq)
661 struct tevent_req *req = tevent_req_callback_data(
662 subreq, struct tevent_req);
663 struct cli_api_pipe_state *state = tevent_req_data(
664 req, struct cli_api_pipe_state);
667 status = rpc_write_recv(subreq);
669 if (tevent_req_nterror(req, status)) {
673 state->rdata = talloc_array(state, uint8_t, RPC_HEADER_LEN);
674 if (tevent_req_nomem(state->rdata, req)) {
679 * We don't need to use rpc_read_send here, the upper layer will cope
680 * with a short read, transport->trans_send could also return less
681 * than state->max_rdata_len.
683 subreq = state->transport->read_send(state, state->ev, state->rdata,
685 state->transport->priv);
686 if (tevent_req_nomem(subreq, req)) {
689 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
692 static void cli_api_pipe_read_done(struct tevent_req *subreq)
694 struct tevent_req *req = tevent_req_callback_data(
695 subreq, struct tevent_req);
696 struct cli_api_pipe_state *state = tevent_req_data(
697 req, struct cli_api_pipe_state);
701 status = state->transport->read_recv(subreq, &received);
703 if (tevent_req_nterror(req, status)) {
706 state->rdata_len = received;
707 tevent_req_done(req);
710 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
711 uint8_t **prdata, uint32_t *prdata_len)
713 struct cli_api_pipe_state *state = tevent_req_data(
714 req, struct cli_api_pipe_state);
717 if (tevent_req_is_nterror(req, &status)) {
721 *prdata = talloc_move(mem_ctx, &state->rdata);
722 *prdata_len = state->rdata_len;
726 /****************************************************************************
727 Send data on an rpc pipe via trans. The data must be the last
728 pdu fragment of an NDR data stream.
730 Receive response data from an rpc pipe, which may be large...
732 Read the first fragment: unfortunately have to use SMBtrans for the first
733 bit, then SMBreadX for subsequent bits.
735 If first fragment received also wasn't the last fragment, continue
736 getting fragments until we _do_ receive the last fragment.
738 Request/Response PDU's look like the following...
740 |<------------------PDU len----------------------------------------------->|
741 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
743 +------------+-----------------+-------------+---------------+-------------+
744 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
745 +------------+-----------------+-------------+---------------+-------------+
747 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
748 signing & sealing being negotiated.
750 ****************************************************************************/
752 struct rpc_api_pipe_state {
753 struct tevent_context *ev;
754 struct rpc_pipe_client *cli;
755 uint8_t expected_pkt_type;
758 DATA_BLOB incoming_frag;
759 struct ncacn_packet *pkt;
763 size_t reply_pdu_offset;
767 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
768 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
769 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq);
771 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
772 struct tevent_context *ev,
773 struct rpc_pipe_client *cli,
774 DATA_BLOB *data, /* Outgoing PDU */
775 uint8_t expected_pkt_type,
778 struct tevent_req *req, *subreq;
779 struct rpc_api_pipe_state *state;
780 uint16_t max_recv_frag;
782 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
788 state->expected_pkt_type = expected_pkt_type;
789 state->call_id = call_id;
790 state->endianness = DCERPC_DREP_LE;
793 * Ensure we're not sending too much.
795 if (data->length > cli->max_xmit_frag) {
796 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
797 return tevent_req_post(req, ev);
800 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
802 if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
803 subreq = rpc_write_send(state, ev, cli->transport,
804 data->data, data->length);
805 if (tevent_req_nomem(subreq, req)) {
806 return tevent_req_post(req, ev);
808 tevent_req_set_callback(subreq, rpc_api_pipe_auth3_done, req);
812 /* get the header first, then fetch the rest once we have
813 * the frag_length available */
814 max_recv_frag = RPC_HEADER_LEN;
816 subreq = cli_api_pipe_send(state, ev, cli->transport,
817 data->data, data->length, max_recv_frag);
818 if (tevent_req_nomem(subreq, req)) {
819 return tevent_req_post(req, ev);
821 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
825 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq)
827 NTSTATUS status = rpc_write_recv(subreq);
828 return tevent_req_simple_finish_ntstatus(subreq, status);
831 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
833 struct tevent_req *req = tevent_req_callback_data(
834 subreq, struct tevent_req);
835 struct rpc_api_pipe_state *state = tevent_req_data(
836 req, struct rpc_api_pipe_state);
838 uint8_t *rdata = NULL;
839 uint32_t rdata_len = 0;
841 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
843 if (tevent_req_nterror(req, status)) {;
844 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
849 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
850 rpccli_pipe_txt(talloc_tos(), state->cli)));
851 tevent_req_done(req);
856 * Move data on state->incoming_frag.
858 state->incoming_frag.data = talloc_move(state, &rdata);
859 state->incoming_frag.length = rdata_len;
860 if (!state->incoming_frag.data) {
861 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
865 /* Ensure we have enough data for a pdu. */
866 subreq = get_complete_frag_send(state, state->ev, state->cli,
867 &state->incoming_frag);
868 if (tevent_req_nomem(subreq, req)) {
871 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
874 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
876 struct tevent_req *req = tevent_req_callback_data(
877 subreq, struct tevent_req);
878 struct rpc_api_pipe_state *state = tevent_req_data(
879 req, struct rpc_api_pipe_state);
881 DATA_BLOB rdata = { .data = NULL };
883 status = get_complete_frag_recv(subreq);
885 if (tevent_req_nterror(req, status)) {
886 DEBUG(5, ("get_complete_frag failed: %s\n",
891 state->pkt = talloc(state, struct ncacn_packet);
894 * TODO: do a real async disconnect ...
896 * For now do it sync...
898 TALLOC_FREE(state->cli->transport);
903 status = dcerpc_pull_ncacn_packet(state->pkt,
904 &state->incoming_frag,
906 if (tevent_req_nterror(req, status)) {
908 * TODO: do a real async disconnect ...
910 * For now do it sync...
912 TALLOC_FREE(state->cli->transport);
916 if (DEBUGLEVEL >= 10) {
917 NDR_PRINT_DEBUG(ncacn_packet, state->pkt);
920 status = cli_pipe_validate_current_pdu(state,
921 state->cli, state->pkt,
922 &state->incoming_frag,
923 state->expected_pkt_type,
928 DBG_DEBUG("got frag len of %zu at offset %zu: %s\n",
929 state->incoming_frag.length,
930 state->reply_pdu_offset,
933 if (state->pkt->ptype != DCERPC_PKT_FAULT && !NT_STATUS_IS_OK(status)) {
935 * TODO: do a real async disconnect ...
937 * For now do it sync...
939 TALLOC_FREE(state->cli->transport);
940 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
942 * TODO: do a real async disconnect ...
944 * For now do it sync...
946 TALLOC_FREE(state->cli->transport);
947 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
949 * TODO: do a real async disconnect ...
951 * For now do it sync...
953 TALLOC_FREE(state->cli->transport);
955 if (tevent_req_nterror(req, status)) {
959 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
960 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
962 * Set the data type correctly for big-endian data on the
965 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
967 rpccli_pipe_txt(talloc_tos(), state->cli)));
968 state->endianness = 0x00; /* BIG ENDIAN */
971 * Check endianness on subsequent packets.
973 if (state->endianness != state->pkt->drep[0]) {
974 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
976 state->endianness?"little":"big",
977 state->pkt->drep[0]?"little":"big"));
979 * TODO: do a real async disconnect ...
981 * For now do it sync...
983 TALLOC_FREE(state->cli->transport);
984 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
988 if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) {
990 * TODO: do a real async disconnect ...
992 * For now do it sync...
994 TALLOC_FREE(state->cli->transport);
995 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
999 /* Now copy the data portion out of the pdu into rbuf. */
1000 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
1001 if (!data_blob_realloc(NULL, &state->reply_pdu,
1002 state->reply_pdu_offset + rdata.length)) {
1004 * TODO: do a real async disconnect ...
1006 * For now do it sync...
1008 TALLOC_FREE(state->cli->transport);
1009 tevent_req_oom(req);
1014 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
1015 rdata.data, rdata.length);
1016 state->reply_pdu_offset += rdata.length;
1018 /* reset state->incoming_frag, there is no need to free it,
1019 * it will be reallocated to the right size the next time
1021 state->incoming_frag.length = 0;
1023 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1024 /* make sure the pdu length is right now that we
1025 * have all the data available (alloc hint may
1026 * have allocated more than was actually used) */
1027 state->reply_pdu.length = state->reply_pdu_offset;
1028 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1029 rpccli_pipe_txt(talloc_tos(), state->cli),
1030 (unsigned)state->reply_pdu.length));
1031 tevent_req_done(req);
1035 subreq = get_complete_frag_send(state, state->ev, state->cli,
1036 &state->incoming_frag);
1037 if (subreq == NULL) {
1039 * TODO: do a real async disconnect ...
1041 * For now do it sync...
1043 TALLOC_FREE(state->cli->transport);
1045 if (tevent_req_nomem(subreq, req)) {
1048 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1051 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1052 struct ncacn_packet **pkt,
1053 DATA_BLOB *reply_pdu)
1055 struct rpc_api_pipe_state *state = tevent_req_data(
1056 req, struct rpc_api_pipe_state);
1059 if (tevent_req_is_nterror(req, &status)) {
1063 /* return data to caller and assign it ownership of memory */
1065 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1066 reply_pdu->length = state->reply_pdu.length;
1067 state->reply_pdu.length = 0;
1069 data_blob_free(&state->reply_pdu);
1073 *pkt = talloc_steal(mem_ctx, state->pkt);
1076 return NT_STATUS_OK;
1079 /*******************************************************************
1080 Creates NTLMSSP auth bind.
1081 ********************************************************************/
1083 static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1084 TALLOC_CTX *mem_ctx,
1085 DATA_BLOB *auth_token,
1086 bool *client_hdr_signing)
1088 struct gensec_security *gensec_security;
1089 DATA_BLOB null_blob = { .data = NULL };
1092 gensec_security = cli->auth->auth_ctx;
1094 DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
1095 status = gensec_update(gensec_security, mem_ctx, null_blob, auth_token);
1097 if (!NT_STATUS_IS_OK(status) &&
1098 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1103 if (client_hdr_signing == NULL) {
1107 if (cli->auth->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1108 *client_hdr_signing = false;
1112 *client_hdr_signing = gensec_have_feature(gensec_security,
1113 GENSEC_FEATURE_SIGN_PKT_HEADER);
1118 /*******************************************************************
1119 Creates the internals of a DCE/RPC bind request or alter context PDU.
1120 ********************************************************************/
1122 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1123 enum dcerpc_pkt_type ptype,
1124 uint32_t rpc_call_id,
1125 const struct ndr_syntax_id *abstract,
1126 const struct ndr_syntax_id *transfer,
1127 const DATA_BLOB *auth_info,
1128 bool client_hdr_signing,
1131 uint16_t auth_len = auth_info->length;
1133 struct dcerpc_ctx_list ctx_list = {
1135 .num_transfer_syntaxes = 1,
1136 .abstract_syntax = *abstract,
1137 .transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer),
1139 union dcerpc_payload u = {
1140 .bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN,
1141 .bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN,
1142 .bind.num_contexts = 1,
1143 .bind.ctx_list = &ctx_list,
1144 .bind.auth_info = *auth_info,
1146 uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1149 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1152 if (client_hdr_signing) {
1153 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1156 status = dcerpc_push_ncacn_packet(mem_ctx,
1162 if (!NT_STATUS_IS_OK(status)) {
1163 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1167 return NT_STATUS_OK;
1170 /*******************************************************************
1171 Creates a DCE/RPC bind request.
1172 ********************************************************************/
1174 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1175 struct rpc_pipe_client *cli,
1176 struct pipe_auth_data *auth,
1177 uint32_t rpc_call_id,
1178 const struct ndr_syntax_id *abstract,
1179 const struct ndr_syntax_id *transfer,
1182 DATA_BLOB auth_token = { .data = NULL };
1183 DATA_BLOB auth_info = { .data = NULL };
1186 if (auth->auth_type != DCERPC_AUTH_TYPE_NONE) {
1187 ret = create_generic_auth_rpc_bind_req(
1188 cli, mem_ctx, &auth_token, &auth->client_hdr_signing);
1190 if (!NT_STATUS_IS_OK(ret) &&
1191 !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1196 if (auth_token.length != 0) {
1197 ret = dcerpc_push_dcerpc_auth(cli,
1200 0, /* auth_pad_length */
1201 auth->auth_context_id,
1204 if (!NT_STATUS_IS_OK(ret)) {
1207 data_blob_free(&auth_token);
1210 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1216 auth->client_hdr_signing,
1218 data_blob_free(&auth_info);
1223 /*******************************************************************
1225 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1226 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1227 and deals with signing/sealing details.
1228 ********************************************************************/
1230 struct rpc_api_pipe_req_state {
1231 struct tevent_context *ev;
1232 struct rpc_pipe_client *cli;
1235 const DATA_BLOB *req_data;
1236 const struct GUID *object_uuid;
1237 uint32_t req_data_sent;
1238 DATA_BLOB req_trailer;
1239 uint32_t req_trailer_sent;
1240 bool verify_bitmask1;
1241 bool verify_pcontext;
1243 DATA_BLOB reply_pdu;
1246 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1247 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1248 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state);
1249 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1250 bool *is_last_frag);
1252 static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1253 struct tevent_context *ev,
1254 struct rpc_pipe_client *cli,
1256 const struct GUID *object_uuid,
1257 const DATA_BLOB *req_data)
1259 struct tevent_req *req, *subreq;
1260 struct rpc_api_pipe_req_state *state;
1264 req = tevent_req_create(mem_ctx, &state,
1265 struct rpc_api_pipe_req_state);
1271 state->op_num = op_num;
1272 state->object_uuid = object_uuid;
1273 state->req_data = req_data;
1274 state->call_id = get_rpc_call_id();
1276 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1277 + RPC_MAX_SIGN_SIZE) {
1278 /* Server is screwed up ! */
1279 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1280 return tevent_req_post(req, ev);
1283 status = prepare_verification_trailer(state);
1284 if (tevent_req_nterror(req, status)) {
1285 return tevent_req_post(req, ev);
1288 status = prepare_next_frag(state, &is_last_frag);
1289 if (tevent_req_nterror(req, status)) {
1290 return tevent_req_post(req, ev);
1294 subreq = rpc_api_pipe_send(state, ev, state->cli,
1296 DCERPC_PKT_RESPONSE,
1298 if (tevent_req_nomem(subreq, req)) {
1299 return tevent_req_post(req, ev);
1301 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1303 subreq = rpc_write_send(state, ev, cli->transport,
1304 state->rpc_out.data,
1305 state->rpc_out.length);
1306 if (tevent_req_nomem(subreq, req)) {
1307 return tevent_req_post(req, ev);
1309 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1315 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state)
1317 struct pipe_auth_data *a = state->cli->auth;
1318 struct dcerpc_sec_verification_trailer *t;
1319 struct ndr_push *ndr = NULL;
1320 enum ndr_err_code ndr_err;
1325 return NT_STATUS_OK;
1328 if (a->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1329 return NT_STATUS_OK;
1332 t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1334 return NT_STATUS_NO_MEMORY;
1337 if (!a->verified_bitmask1) {
1338 t->commands = talloc_realloc(t, t->commands,
1339 struct dcerpc_sec_vt,
1340 t->count.count + 1);
1341 if (t->commands == NULL) {
1342 return NT_STATUS_NO_MEMORY;
1344 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
1345 .command = DCERPC_SEC_VT_COMMAND_BITMASK1,
1346 .u.bitmask1 = (a->client_hdr_signing) ?
1347 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING :
1350 state->verify_bitmask1 = true;
1353 if (!state->cli->verified_pcontext) {
1354 t->commands = talloc_realloc(t, t->commands,
1355 struct dcerpc_sec_vt,
1356 t->count.count + 1);
1357 if (t->commands == NULL) {
1358 return NT_STATUS_NO_MEMORY;
1360 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
1361 .command = DCERPC_SEC_VT_COMMAND_PCONTEXT,
1362 .u.pcontext.abstract_syntax =
1363 state->cli->abstract_syntax,
1364 .u.pcontext.transfer_syntax =
1365 state->cli->transfer_syntax,
1367 state->verify_pcontext = true;
1370 if (!a->hdr_signing) {
1371 t->commands = talloc_realloc(t, t->commands,
1372 struct dcerpc_sec_vt,
1373 t->count.count + 1);
1374 if (t->commands == NULL) {
1375 return NT_STATUS_NO_MEMORY;
1377 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
1378 .command = DCERPC_SEC_VT_COMMAND_HEADER2,
1379 .u.header2.ptype = DCERPC_PKT_REQUEST,
1380 .u.header2.drep[0] = DCERPC_DREP_LE,
1381 .u.header2.call_id = state->call_id,
1382 .u.header2.context_id = 0,
1383 .u.header2.opnum = state->op_num,
1387 if (t->count.count == 0) {
1389 return NT_STATUS_OK;
1392 t->commands[t->count.count - 1].command |= DCERPC_SEC_VT_COMMAND_END;
1394 if (DEBUGLEVEL >= 10) {
1395 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1398 ndr = ndr_push_init_ctx(state);
1400 return NT_STATUS_NO_MEMORY;
1403 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1404 NDR_SCALARS | NDR_BUFFERS,
1407 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1408 return ndr_map_error2ntstatus(ndr_err);
1410 state->req_trailer = ndr_push_blob(ndr);
1412 align = state->req_data->length & 0x3;
1419 const uint8_t zeros[4] = { 0, };
1421 ok = data_blob_append(ndr, &state->req_trailer, zeros, pad);
1423 return NT_STATUS_NO_MEMORY;
1426 /* move the padding to the start */
1427 p = state->req_trailer.data;
1428 memmove(p + pad, p, state->req_trailer.length - pad);
1432 return NT_STATUS_OK;
1435 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1443 size_t data_thistime;
1444 size_t trailer_left;
1445 size_t trailer_thistime = 0;
1447 size_t total_thistime;
1450 union dcerpc_payload u;
1452 data_left = state->req_data->length - state->req_data_sent;
1453 trailer_left = state->req_trailer.length - state->req_trailer_sent;
1454 total_left = data_left + trailer_left;
1455 if ((total_left < data_left) || (total_left < trailer_left)) {
1459 return NT_STATUS_INVALID_PARAMETER_MIX;
1462 status = dcerpc_guess_sizes(state->cli->auth,
1463 DCERPC_REQUEST_LENGTH, total_left,
1464 state->cli->max_xmit_frag,
1466 &frag_len, &auth_len, &pad_len);
1467 if (!NT_STATUS_IS_OK(status)) {
1471 if (state->req_data_sent == 0) {
1472 flags = DCERPC_PFC_FLAG_FIRST;
1475 if (total_thistime == total_left) {
1476 flags |= DCERPC_PFC_FLAG_LAST;
1479 data_thistime = MIN(total_thistime, data_left);
1480 if (data_thistime < total_thistime) {
1481 trailer_thistime = total_thistime - data_thistime;
1484 data_blob_free(&state->rpc_out);
1486 u = (union dcerpc_payload) {
1487 .request.alloc_hint = total_left,
1488 .request.context_id = 0,
1489 .request.opnum = state->op_num,
1492 if (state->object_uuid) {
1493 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1494 u.request.object.object = *state->object_uuid;
1495 frag_len += ndr_size_GUID(state->object_uuid, 0);
1498 status = dcerpc_push_ncacn_packet(state,
1505 if (!NT_STATUS_IS_OK(status)) {
1509 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1510 * compute it right for requests because the auth trailer is missing
1512 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1514 if (data_thistime > 0) {
1515 /* Copy in the data. */
1516 ok = data_blob_append(NULL, &state->rpc_out,
1517 state->req_data->data + state->req_data_sent,
1520 return NT_STATUS_NO_MEMORY;
1522 state->req_data_sent += data_thistime;
1525 if (trailer_thistime > 0) {
1526 /* Copy in the verification trailer. */
1527 ok = data_blob_append(NULL, &state->rpc_out,
1528 state->req_trailer.data + state->req_trailer_sent,
1531 return NT_STATUS_NO_MEMORY;
1533 state->req_trailer_sent += trailer_thistime;
1536 switch (state->cli->auth->auth_level) {
1537 case DCERPC_AUTH_LEVEL_NONE:
1538 case DCERPC_AUTH_LEVEL_CONNECT:
1540 case DCERPC_AUTH_LEVEL_PACKET:
1541 case DCERPC_AUTH_LEVEL_INTEGRITY:
1542 case DCERPC_AUTH_LEVEL_PRIVACY:
1543 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1545 if (!NT_STATUS_IS_OK(status)) {
1550 return NT_STATUS_INVALID_PARAMETER;
1553 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1558 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1560 struct tevent_req *req = tevent_req_callback_data(
1561 subreq, struct tevent_req);
1562 struct rpc_api_pipe_req_state *state = tevent_req_data(
1563 req, struct rpc_api_pipe_req_state);
1567 status = rpc_write_recv(subreq);
1568 TALLOC_FREE(subreq);
1569 if (tevent_req_nterror(req, status)) {
1573 status = prepare_next_frag(state, &is_last_frag);
1574 if (tevent_req_nterror(req, status)) {
1579 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1581 DCERPC_PKT_RESPONSE,
1583 if (tevent_req_nomem(subreq, req)) {
1586 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1588 subreq = rpc_write_send(state, state->ev,
1589 state->cli->transport,
1590 state->rpc_out.data,
1591 state->rpc_out.length);
1592 if (tevent_req_nomem(subreq, req)) {
1595 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1600 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1602 struct tevent_req *req = tevent_req_callback_data(
1603 subreq, struct tevent_req);
1604 struct rpc_api_pipe_req_state *state = tevent_req_data(
1605 req, struct rpc_api_pipe_req_state);
1608 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1609 TALLOC_FREE(subreq);
1610 if (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 struct rpc_pipe_client *cli)
1661 const struct ndr_syntax_id *transfer = &cli->transfer_syntax;
1662 struct dcerpc_ack_ctx ctx;
1665 if (r->secondary_address_size == 0) {
1666 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)\n"));
1669 if (r->num_results < 1 || !r->ctx_list) {
1673 ctx = r->ctx_list[0];
1675 /* check the transfer syntax */
1676 equal = ndr_syntax_id_equal(&ctx.syntax, transfer);
1678 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1682 if (r->num_results != 0x1 || ctx.result != 0) {
1683 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1684 r->num_results, ctx.reason.value));
1687 DEBUG(5,("check_bind_response: accepted!\n"));
1691 /*******************************************************************
1692 Creates a DCE/RPC bind authentication response.
1693 This is the packet that is sent back to the server once we
1694 have received a BIND-ACK, to finish the third leg of
1695 the authentication handshake.
1696 ********************************************************************/
1698 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1699 struct rpc_pipe_client *cli,
1700 struct pipe_auth_data *auth,
1701 uint32_t rpc_call_id,
1702 DATA_BLOB *pauth_blob,
1706 union dcerpc_payload u = { .auth3._pad = 0, };
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 blob
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)) {
1830 tevent_req_nterror(req, status);
1831 return tevent_req_post(req, ev);
1834 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1835 DCERPC_PKT_BIND_ACK, state->rpc_call_id);
1836 if (tevent_req_nomem(subreq, req)) {
1837 return tevent_req_post(req, ev);
1839 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1843 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1845 struct tevent_req *req = tevent_req_callback_data(
1846 subreq, struct tevent_req);
1847 struct rpc_pipe_bind_state *state = tevent_req_data(
1848 req, struct rpc_pipe_bind_state);
1849 struct pipe_auth_data *pauth = state->cli->auth;
1850 struct gensec_security *gensec_security;
1851 struct ncacn_packet *pkt = NULL;
1852 struct dcerpc_auth auth;
1853 DATA_BLOB auth_token = { .data = NULL };
1856 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
1857 TALLOC_FREE(subreq);
1858 if (tevent_req_nterror(req, status)) {
1859 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1860 rpccli_pipe_txt(talloc_tos(), state->cli),
1861 nt_errstr(status)));
1866 tevent_req_done(req);
1870 if (!check_bind_response(&pkt->u.bind_ack, state->cli)) {
1871 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1872 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1876 if (pkt->ptype == DCERPC_PKT_BIND_ACK) {
1877 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1878 if (pauth->client_hdr_signing) {
1879 pauth->hdr_signing = true;
1884 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1886 if (pauth->auth_type == DCERPC_AUTH_TYPE_NONE) {
1887 /* Bind complete. */
1888 tevent_req_done(req);
1892 if (pkt->auth_length == 0) {
1893 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1897 /* get auth credentials */
1898 status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
1899 &pkt->u.bind_ack.auth_info,
1901 if (tevent_req_nterror(req, status)) {
1902 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1903 nt_errstr(status)));
1907 if (auth.auth_type != pauth->auth_type) {
1908 DBG_ERR("Auth type %u mismatch expected %u.\n",
1909 auth.auth_type, pauth->auth_type);
1910 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1914 if (auth.auth_level != pauth->auth_level) {
1915 DBG_ERR("Auth level %u mismatch expected %u.\n",
1916 auth.auth_level, pauth->auth_level);
1917 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1921 if (auth.auth_context_id != pauth->auth_context_id) {
1922 DBG_ERR("Auth context id %"PRIu32" mismatch "
1923 "expected %"PRIu32".\n",
1924 auth.auth_context_id,
1925 pauth->auth_context_id);
1926 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1931 * For authenticated binds we may need to do 3 or 4 leg binds.
1934 if (pauth->auth_type == DCERPC_AUTH_TYPE_NONE) {
1935 /* Bind complete. */
1936 tevent_req_done(req);
1940 gensec_security = pauth->auth_ctx;
1942 status = gensec_update(gensec_security, state,
1943 auth.credentials, &auth_token);
1944 if (NT_STATUS_EQUAL(status,
1945 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1946 status = rpc_bind_next_send(req, state,
1948 } else if (NT_STATUS_IS_OK(status)) {
1949 if (pauth->hdr_signing) {
1950 gensec_want_feature(gensec_security,
1951 GENSEC_FEATURE_SIGN_PKT_HEADER);
1954 if (auth_token.length == 0) {
1955 /* Bind complete. */
1956 tevent_req_done(req);
1959 status = rpc_bind_finish_send(req, state,
1963 if (!NT_STATUS_IS_OK(status)) {
1964 tevent_req_nterror(req, status);
1969 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1970 struct rpc_pipe_bind_state *state,
1971 DATA_BLOB *auth_token)
1973 struct pipe_auth_data *auth = state->cli->auth;
1974 struct tevent_req *subreq;
1977 /* Now prepare the alter context pdu. */
1978 data_blob_free(&state->rpc_out);
1980 status = create_rpc_alter_context(state, auth,
1982 &state->cli->abstract_syntax,
1983 &state->cli->transfer_syntax,
1986 if (!NT_STATUS_IS_OK(status)) {
1990 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1991 &state->rpc_out, DCERPC_PKT_ALTER_RESP,
1992 state->rpc_call_id);
1993 if (subreq == NULL) {
1994 return NT_STATUS_NO_MEMORY;
1996 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1997 return NT_STATUS_OK;
2000 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
2001 struct rpc_pipe_bind_state *state,
2002 DATA_BLOB *auth_token)
2004 struct pipe_auth_data *auth = state->cli->auth;
2005 struct tevent_req *subreq;
2008 state->auth3 = true;
2010 /* Now prepare the auth3 context pdu. */
2011 data_blob_free(&state->rpc_out);
2013 status = create_rpc_bind_auth3(state, state->cli, auth,
2017 if (!NT_STATUS_IS_OK(status)) {
2021 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2022 &state->rpc_out, DCERPC_PKT_AUTH3,
2023 state->rpc_call_id);
2024 if (subreq == NULL) {
2025 return NT_STATUS_NO_MEMORY;
2027 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2028 return NT_STATUS_OK;
2031 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2033 return tevent_req_simple_recv_ntstatus(req);
2036 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2037 struct pipe_auth_data *auth)
2039 TALLOC_CTX *frame = talloc_stackframe();
2040 struct tevent_context *ev;
2041 struct tevent_req *req;
2042 NTSTATUS status = NT_STATUS_OK;
2044 ev = samba_tevent_context_init(frame);
2046 status = NT_STATUS_NO_MEMORY;
2050 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2052 status = NT_STATUS_NO_MEMORY;
2056 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2060 status = rpc_pipe_bind_recv(req);
2066 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2068 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2069 unsigned int timeout)
2071 if (rpc_cli == NULL) {
2072 return RPCCLI_DEFAULT_TIMEOUT;
2075 if (rpc_cli->binding_handle == NULL) {
2076 return RPCCLI_DEFAULT_TIMEOUT;
2079 return dcerpc_binding_handle_set_timeout(rpc_cli->binding_handle,
2083 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2085 if (rpc_cli == NULL) {
2089 if (rpc_cli->binding_handle == NULL) {
2093 return dcerpc_binding_handle_is_connected(rpc_cli->binding_handle);
2096 struct rpccli_bh_state {
2097 struct rpc_pipe_client *rpc_cli;
2100 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2102 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2103 struct rpccli_bh_state);
2104 struct rpc_cli_transport *transport = hs->rpc_cli->transport;
2106 if (transport == NULL) {
2110 if (transport->is_connected == NULL) {
2114 return transport->is_connected(transport->priv);
2117 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2120 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2121 struct rpccli_bh_state);
2122 struct rpc_cli_transport *transport = hs->rpc_cli->transport;
2125 if (transport == NULL) {
2126 return RPCCLI_DEFAULT_TIMEOUT;
2129 if (transport->set_timeout == NULL) {
2130 return RPCCLI_DEFAULT_TIMEOUT;
2133 old = transport->set_timeout(transport->priv, timeout);
2135 return RPCCLI_DEFAULT_TIMEOUT;
2141 static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
2142 enum dcerpc_AuthType *auth_type,
2143 enum dcerpc_AuthLevel *auth_level)
2145 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2146 struct rpccli_bh_state);
2148 if (hs->rpc_cli == NULL) {
2152 if (hs->rpc_cli->auth == NULL) {
2156 *auth_type = hs->rpc_cli->auth->auth_type;
2157 *auth_level = hs->rpc_cli->auth->auth_level;
2160 struct rpccli_bh_raw_call_state {
2166 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2168 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2169 struct tevent_context *ev,
2170 struct dcerpc_binding_handle *h,
2171 const struct GUID *object,
2174 const uint8_t *in_data,
2177 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2178 struct rpccli_bh_state);
2179 struct tevent_req *req;
2180 struct rpccli_bh_raw_call_state *state;
2182 struct tevent_req *subreq;
2184 req = tevent_req_create(mem_ctx, &state,
2185 struct rpccli_bh_raw_call_state);
2189 state->in_data.data = discard_const_p(uint8_t, in_data);
2190 state->in_data.length = in_length;
2192 ok = rpccli_bh_is_connected(h);
2194 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2195 return tevent_req_post(req, ev);
2198 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2199 opnum, object, &state->in_data);
2200 if (tevent_req_nomem(subreq, req)) {
2201 return tevent_req_post(req, ev);
2203 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2208 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2210 struct tevent_req *req =
2211 tevent_req_callback_data(subreq,
2213 struct rpccli_bh_raw_call_state *state =
2214 tevent_req_data(req,
2215 struct rpccli_bh_raw_call_state);
2218 state->out_flags = 0;
2220 /* TODO: support bigendian responses */
2222 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2223 TALLOC_FREE(subreq);
2224 if (tevent_req_nterror(req, status)) {
2228 tevent_req_done(req);
2231 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2232 TALLOC_CTX *mem_ctx,
2235 uint32_t *out_flags)
2237 struct rpccli_bh_raw_call_state *state =
2238 tevent_req_data(req,
2239 struct rpccli_bh_raw_call_state);
2242 if (tevent_req_is_nterror(req, &status)) {
2243 tevent_req_received(req);
2247 *out_data = talloc_move(mem_ctx, &state->out_data.data);
2248 *out_length = state->out_data.length;
2249 *out_flags = state->out_flags;
2250 tevent_req_received(req);
2251 return NT_STATUS_OK;
2254 struct rpccli_bh_disconnect_state {
2258 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2259 struct tevent_context *ev,
2260 struct dcerpc_binding_handle *h)
2262 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2263 struct rpccli_bh_state);
2264 struct tevent_req *req;
2265 struct rpccli_bh_disconnect_state *state;
2268 req = tevent_req_create(mem_ctx, &state,
2269 struct rpccli_bh_disconnect_state);
2274 ok = rpccli_bh_is_connected(h);
2276 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2277 return tevent_req_post(req, ev);
2281 * TODO: do a real async disconnect ...
2283 * For now we do it sync...
2285 TALLOC_FREE(hs->rpc_cli->transport);
2288 tevent_req_done(req);
2289 return tevent_req_post(req, ev);
2292 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2294 return tevent_req_simple_recv_ntstatus(req);
2297 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2302 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2303 ndr_flags_type ndr_flags,
2304 const void *_struct_ptr,
2305 const struct ndr_interface_call *call)
2307 void *struct_ptr = discard_const(_struct_ptr);
2309 if (DEBUGLEVEL < 10) {
2313 if (ndr_flags & NDR_IN) {
2314 ndr_print_function_debug(call->ndr_print,
2319 if (ndr_flags & NDR_OUT) {
2320 ndr_print_function_debug(call->ndr_print,
2327 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2329 .is_connected = rpccli_bh_is_connected,
2330 .set_timeout = rpccli_bh_set_timeout,
2331 .auth_info = rpccli_bh_auth_info,
2332 .raw_call_send = rpccli_bh_raw_call_send,
2333 .raw_call_recv = rpccli_bh_raw_call_recv,
2334 .disconnect_send = rpccli_bh_disconnect_send,
2335 .disconnect_recv = rpccli_bh_disconnect_recv,
2337 .ref_alloc = rpccli_bh_ref_alloc,
2338 .do_ndr_print = rpccli_bh_do_ndr_print,
2341 /* initialise a rpc_pipe_client binding handle */
2342 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2343 const struct GUID *object,
2344 const struct ndr_interface_table *table)
2346 struct dcerpc_binding_handle *h;
2347 struct rpccli_bh_state *hs;
2349 h = dcerpc_binding_handle_create(c,
2354 struct rpccli_bh_state,
2364 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2365 struct pipe_auth_data **presult)
2367 struct pipe_auth_data *result;
2368 struct auth_generic_state *auth_generic_ctx;
2371 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2372 if (result == NULL) {
2373 return NT_STATUS_NO_MEMORY;
2376 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2377 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2378 result->auth_context_id = 0;
2380 status = auth_generic_client_prepare(result,
2382 if (!NT_STATUS_IS_OK(status)) {
2383 DEBUG(1, ("Failed to create auth_generic context: %s\n",
2384 nt_errstr(status)));
2387 status = auth_generic_set_username(auth_generic_ctx, "");
2388 if (!NT_STATUS_IS_OK(status)) {
2389 DEBUG(1, ("Failed to set username: %s\n",
2390 nt_errstr(status)));
2393 status = auth_generic_set_domain(auth_generic_ctx, "");
2394 if (!NT_STATUS_IS_OK(status)) {
2395 DEBUG(1, ("Failed to set domain: %s\n",
2396 nt_errstr(status)));
2400 status = gensec_set_credentials(auth_generic_ctx->gensec_security,
2401 auth_generic_ctx->credentials);
2402 if (!NT_STATUS_IS_OK(status)) {
2403 DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
2404 nt_errstr(status)));
2407 talloc_unlink(auth_generic_ctx, auth_generic_ctx->credentials);
2408 auth_generic_ctx->credentials = NULL;
2410 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2411 talloc_free(auth_generic_ctx);
2413 return NT_STATUS_OK;
2416 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2417 enum dcerpc_AuthType auth_type,
2418 enum dcerpc_AuthLevel auth_level,
2420 const char *target_service,
2422 const char *username,
2423 const char *password,
2424 enum credentials_use_kerberos use_kerberos,
2425 struct netlogon_creds_CredentialState *creds,
2426 struct pipe_auth_data **presult)
2428 struct auth_generic_state *auth_generic_ctx;
2429 struct pipe_auth_data *result;
2432 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2433 if (result == NULL) {
2434 return NT_STATUS_NO_MEMORY;
2437 result->auth_type = auth_type;
2438 result->auth_level = auth_level;
2439 result->auth_context_id = 1;
2441 status = auth_generic_client_prepare(result,
2443 if (!NT_STATUS_IS_OK(status)) {
2447 status = auth_generic_set_username(auth_generic_ctx, username);
2448 if (!NT_STATUS_IS_OK(status)) {
2452 status = auth_generic_set_domain(auth_generic_ctx, domain);
2453 if (!NT_STATUS_IS_OK(status)) {
2457 status = auth_generic_set_password(auth_generic_ctx, password);
2458 if (!NT_STATUS_IS_OK(status)) {
2462 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2463 if (!NT_STATUS_IS_OK(status)) {
2467 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2468 if (!NT_STATUS_IS_OK(status)) {
2472 cli_credentials_set_kerberos_state(auth_generic_ctx->credentials,
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 */
2560 NULL, /* password */
2561 CRED_USE_KERBEROS_DISABLED,
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 if (result->desthost == NULL) {
2590 status = NT_STATUS_NO_MEMORY;
2594 result->srv_name_slash = talloc_asprintf_strupper_m(
2595 result, "\\\\%s", result->desthost);
2596 if (result->srv_name_slash == NULL) {
2597 status = NT_STATUS_NO_MEMORY;
2601 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2603 if (ss_addr == NULL) {
2604 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2605 status = NT_STATUS_NOT_FOUND;
2612 status = open_socket_out(&addr, port, 60*1000, &fd);
2613 if (!NT_STATUS_IS_OK(status)) {
2616 set_socket_options(fd, lp_socket_options());
2618 status = rpc_transport_sock_init(result, fd, &result->transport);
2619 if (!NT_STATUS_IS_OK(status)) {
2624 result->transport->transport = NCACN_IP_TCP;
2626 result->binding_handle = rpccli_bh_create(result, NULL, table);
2627 if (result->binding_handle == NULL) {
2628 TALLOC_FREE(result);
2629 return NT_STATUS_NO_MEMORY;
2633 return NT_STATUS_OK;
2636 TALLOC_FREE(result);
2640 static NTSTATUS rpccli_epm_map_binding(
2641 struct dcerpc_binding_handle *epm_connection,
2642 struct dcerpc_binding *binding,
2643 TALLOC_CTX *mem_ctx,
2646 TALLOC_CTX *frame = talloc_stackframe();
2647 enum dcerpc_transport_t transport =
2648 dcerpc_binding_get_transport(binding);
2649 enum dcerpc_transport_t res_transport;
2650 struct dcerpc_binding *res_binding = NULL;
2651 struct epm_twr_t *map_tower = NULL;
2652 struct epm_twr_p_t res_towers = { .twr = NULL };
2653 struct policy_handle *entry_handle = NULL;
2654 uint32_t num_towers = 0;
2655 const uint32_t max_towers = 1;
2656 const char *endpoint = NULL;
2661 map_tower = talloc_zero(frame, struct epm_twr_t);
2662 if (map_tower == NULL) {
2666 status = dcerpc_binding_build_tower(
2667 frame, binding, &(map_tower->tower));
2668 if (!NT_STATUS_IS_OK(status)) {
2669 DBG_DEBUG("dcerpc_binding_build_tower failed: %s\n",
2674 res_towers.twr = talloc_array(frame, struct epm_twr_t, max_towers);
2675 if (res_towers.twr == NULL) {
2679 entry_handle = talloc_zero(frame, struct policy_handle);
2680 if (entry_handle == NULL) {
2684 status = dcerpc_epm_Map(
2695 if (!NT_STATUS_IS_OK(status)) {
2696 DBG_DEBUG("dcerpc_epm_Map failed: %s\n", nt_errstr(status));
2700 if (result != EPMAPPER_STATUS_OK) {
2701 DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32"\n", result);
2702 status = NT_STATUS_NOT_FOUND;
2706 if (num_towers != 1) {
2707 DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32" towers\n",
2709 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2713 status = dcerpc_binding_from_tower(
2714 frame, &(res_towers.twr->tower), &res_binding);
2715 if (!NT_STATUS_IS_OK(status)) {
2716 DBG_DEBUG("dcerpc_binding_from_tower failed: %s\n",
2721 res_transport = dcerpc_binding_get_transport(res_binding);
2722 if (res_transport != transport) {
2723 DBG_DEBUG("dcerpc_epm_Map returned transport %d, "
2727 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2731 endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
2732 if (endpoint == NULL) {
2733 DBG_DEBUG("dcerpc_epm_Map returned no endpoint\n");
2734 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2738 tmp = talloc_strdup(mem_ctx, endpoint);
2744 status = NT_STATUS_OK;
2748 status = NT_STATUS_NO_MEMORY;
2754 static NTSTATUS rpccli_epm_map_interface(
2755 struct dcerpc_binding_handle *epm_connection,
2756 enum dcerpc_transport_t transport,
2757 const struct ndr_syntax_id *iface,
2758 TALLOC_CTX *mem_ctx,
2761 struct dcerpc_binding *binding = NULL;
2762 char *endpoint = NULL;
2765 status = dcerpc_parse_binding(mem_ctx, "", &binding);
2766 if (!NT_STATUS_IS_OK(status)) {
2767 DBG_DEBUG("dcerpc_parse_binding failed: %s\n",
2772 status = dcerpc_binding_set_transport(binding, transport);
2773 if (!NT_STATUS_IS_OK(status)) {
2774 DBG_DEBUG("dcerpc_binding_set_transport failed: %s\n",
2779 status = dcerpc_binding_set_abstract_syntax(binding, iface);
2780 if (!NT_STATUS_IS_OK(status)) {
2781 DBG_DEBUG("dcerpc_binding_set_abstract_syntax failed: %s\n",
2786 status = rpccli_epm_map_binding(
2787 epm_connection, binding, mem_ctx, &endpoint);
2788 if (!NT_STATUS_IS_OK(status)) {
2789 DBG_DEBUG("rpccli_epm_map_binding failed: %s\n",
2793 *pendpoint = endpoint;
2796 TALLOC_FREE(binding);
2801 * Determine the tcp port on which a dcerpc interface is listening
2802 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2805 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2806 const struct sockaddr_storage *addr,
2807 const struct ndr_interface_table *table,
2811 struct rpc_pipe_client *epm_pipe = NULL;
2812 struct pipe_auth_data *auth = NULL;
2813 char *endpoint = NULL;
2814 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2816 if (pport == NULL) {
2817 status = NT_STATUS_INVALID_PARAMETER;
2821 if (ndr_syntax_id_equal(&table->syntax_id,
2822 &ndr_table_epmapper.syntax_id)) {
2824 status = NT_STATUS_OK;
2828 /* open the connection to the endpoint mapper */
2829 status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2830 &ndr_table_epmapper,
2833 if (!NT_STATUS_IS_OK(status)) {
2837 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2838 if (!NT_STATUS_IS_OK(status)) {
2842 status = rpc_pipe_bind(epm_pipe, auth);
2843 if (!NT_STATUS_IS_OK(status)) {
2847 status = rpccli_epm_map_interface(
2848 epm_pipe->binding_handle,
2853 if (!NT_STATUS_IS_OK(status)) {
2854 DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
2859 *pport = (uint16_t)atoi(endpoint);
2862 TALLOC_FREE(tmp_ctx);
2867 * Create a rpc pipe client struct, connecting to a host via tcp.
2868 * The port is determined by asking the endpoint mapper on the given
2871 static NTSTATUS rpc_pipe_open_tcp(
2872 TALLOC_CTX *mem_ctx,
2874 const struct sockaddr_storage *addr,
2875 const struct ndr_interface_table *table,
2876 struct rpc_pipe_client **presult)
2881 status = rpc_pipe_get_tcp_port(host, addr, table, &port);
2882 if (!NT_STATUS_IS_OK(status)) {
2886 return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2890 static NTSTATUS rpc_pipe_get_ncalrpc_name(
2891 const struct ndr_syntax_id *iface,
2892 TALLOC_CTX *mem_ctx,
2893 char **psocket_name)
2895 TALLOC_CTX *frame = talloc_stackframe();
2896 struct rpc_pipe_client *epm_pipe = NULL;
2897 struct pipe_auth_data *auth = NULL;
2898 NTSTATUS status = NT_STATUS_OK;
2901 is_epm = ndr_syntax_id_equal(iface, &ndr_table_epmapper.syntax_id);
2903 char *endpoint = talloc_strdup(mem_ctx, "EPMAPPER");
2904 if (endpoint == NULL) {
2905 status = NT_STATUS_NO_MEMORY;
2908 *psocket_name = endpoint;
2912 status = rpc_pipe_open_ncalrpc(
2913 frame, &ndr_table_epmapper, &epm_pipe);
2914 if (!NT_STATUS_IS_OK(status)) {
2915 DBG_DEBUG("rpc_pipe_open_ncalrpc failed: %s\n",
2920 status = rpccli_anon_bind_data(epm_pipe, &auth);
2921 if (!NT_STATUS_IS_OK(status)) {
2922 DBG_DEBUG("rpccli_anon_bind_data failed: %s\n",
2927 status = rpc_pipe_bind(epm_pipe, auth);
2928 if (!NT_STATUS_IS_OK(status)) {
2929 DBG_DEBUG("rpc_pipe_bind failed: %s\n", nt_errstr(status));
2933 status = rpccli_epm_map_interface(
2934 epm_pipe->binding_handle,
2939 if (!NT_STATUS_IS_OK(status)) {
2940 DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
2949 /********************************************************************
2950 Create a rpc pipe client struct, connecting to a unix domain socket
2951 ********************************************************************/
2952 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx,
2953 const struct ndr_interface_table *table,
2954 struct rpc_pipe_client **presult)
2956 char *socket_name = NULL;
2957 struct rpc_pipe_client *result;
2958 struct sockaddr_un addr = { .sun_family = AF_UNIX };
2959 socklen_t salen = sizeof(addr);
2964 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2965 if (result == NULL) {
2966 return NT_STATUS_NO_MEMORY;
2969 status = rpc_pipe_get_ncalrpc_name(
2970 &table->syntax_id, result, &socket_name);
2971 if (!NT_STATUS_IS_OK(status)) {
2972 DBG_DEBUG("rpc_pipe_get_ncalrpc_name failed: %s\n",
2979 sizeof(addr.sun_path),
2983 if ((pathlen < 0) || ((size_t)pathlen >= sizeof(addr.sun_path))) {
2984 DBG_DEBUG("socket_path for %s too long\n", socket_name);
2985 status = NT_STATUS_NAME_TOO_LONG;
2988 TALLOC_FREE(socket_name);
2990 result->abstract_syntax = table->syntax_id;
2991 result->transfer_syntax = ndr_transfer_syntax_ndr;
2993 result->desthost = get_myname(result);
2994 if (result->desthost == NULL) {
2995 status = NT_STATUS_NO_MEMORY;
2999 result->srv_name_slash = talloc_asprintf_strupper_m(
3000 result, "\\\\%s", result->desthost);
3001 if (result->srv_name_slash == NULL) {
3002 status = NT_STATUS_NO_MEMORY;
3006 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3008 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3010 status = map_nt_error_from_unix(errno);
3014 if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
3015 DBG_WARNING("connect(%s) failed: %s\n",
3018 status = map_nt_error_from_unix(errno);
3022 status = rpc_transport_sock_init(result, fd, &result->transport);
3023 if (!NT_STATUS_IS_OK(status)) {
3028 result->transport->transport = NCALRPC;
3030 result->binding_handle = rpccli_bh_create(result, NULL, table);
3031 if (result->binding_handle == NULL) {
3032 status = NT_STATUS_NO_MEMORY;
3037 return NT_STATUS_OK;
3043 TALLOC_FREE(result);
3047 NTSTATUS rpc_pipe_open_local_np(
3048 TALLOC_CTX *mem_ctx,
3049 const struct ndr_interface_table *table,
3050 const char *remote_client_name,
3051 const struct tsocket_address *remote_client_addr,
3052 const char *local_server_name,
3053 const struct tsocket_address *local_server_addr,
3054 const struct auth_session_info *session_info,
3055 struct rpc_pipe_client **presult)
3057 struct rpc_pipe_client *result = NULL;
3058 struct pipe_auth_data *auth = NULL;
3059 const char *pipe_name = NULL;
3060 struct tstream_context *npa_stream = NULL;
3061 NTSTATUS status = NT_STATUS_NO_MEMORY;
3064 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3065 if (result == NULL) {
3068 result->abstract_syntax = table->syntax_id;
3069 result->transfer_syntax = ndr_transfer_syntax_ndr;
3070 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3072 pipe_name = dcerpc_default_transport_endpoint(
3073 result, NCACN_NP, table);
3074 if (pipe_name == NULL) {
3075 DBG_DEBUG("dcerpc_default_transport_endpoint failed\n");
3076 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3080 if (local_server_name == NULL) {
3081 result->desthost = get_myname(result);
3083 result->desthost = talloc_strdup(result, local_server_name);
3085 if (result->desthost == NULL) {
3088 result->srv_name_slash = talloc_asprintf_strupper_m(
3089 result, "\\\\%s", result->desthost);
3090 if (result->srv_name_slash == NULL) {
3094 ret = local_np_connect(
3106 DBG_DEBUG("local_np_connect for %s and "
3107 "user %s\\%s failed: %s\n",
3109 session_info->info->domain_name,
3110 session_info->info->account_name,
3112 status = map_nt_error_from_unix(ret);
3116 status = rpc_transport_tstream_init(
3117 result, &npa_stream, &result->transport);
3118 if (!NT_STATUS_IS_OK(status)) {
3119 DBG_DEBUG("rpc_transport_tstream_init failed: %s\n",
3124 result->binding_handle = rpccli_bh_create(result, NULL, table);
3125 if (result->binding_handle == NULL) {
3126 status = NT_STATUS_NO_MEMORY;
3127 DBG_DEBUG("Failed to create binding handle.\n");
3131 status = rpccli_anon_bind_data(result, &auth);
3132 if (!NT_STATUS_IS_OK(status)) {
3133 DBG_DEBUG("rpccli_anon_bind_data failed: %s\n",
3138 status = rpc_pipe_bind(result, auth);
3139 if (!NT_STATUS_IS_OK(status)) {
3140 DBG_DEBUG("rpc_pipe_bind failed: %s\n", nt_errstr(status));
3145 return NT_STATUS_OK;
3148 TALLOC_FREE(result);
3152 struct rpc_pipe_client_np_ref {
3153 struct cli_state *cli;
3154 struct rpc_pipe_client *pipe;
3157 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3159 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3163 /****************************************************************************
3164 Open a named pipe over SMB to a remote server.
3166 * CAVEAT CALLER OF THIS FUNCTION:
3167 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3168 * so be sure that this function is called AFTER any structure (vs pointer)
3169 * assignment of the cli. In particular, libsmbclient does structure
3170 * assignments of cli, which invalidates the data in the returned
3171 * rpc_pipe_client if this function is called before the structure assignment
3174 ****************************************************************************/
3176 struct rpc_pipe_open_np_state {
3177 struct cli_state *cli;
3178 const struct ndr_interface_table *table;
3179 struct rpc_pipe_client *result;
3182 static void rpc_pipe_open_np_done(struct tevent_req *subreq);
3184 struct tevent_req *rpc_pipe_open_np_send(
3185 TALLOC_CTX *mem_ctx,
3186 struct tevent_context *ev,
3187 struct cli_state *cli,
3188 const struct ndr_interface_table *table)
3190 struct tevent_req *req = NULL, *subreq = NULL;
3191 struct rpc_pipe_open_np_state *state = NULL;
3192 struct rpc_pipe_client *result = NULL;
3194 req = tevent_req_create(
3195 mem_ctx, &state, struct rpc_pipe_open_np_state);
3200 state->table = table;
3202 state->result = talloc_zero(state, struct rpc_pipe_client);
3203 if (tevent_req_nomem(state->result, req)) {
3204 return tevent_req_post(req, ev);
3206 result = state->result;
3208 result->abstract_syntax = table->syntax_id;
3209 result->transfer_syntax = ndr_transfer_syntax_ndr;
3211 result->desthost = talloc_strdup(
3212 result, smbXcli_conn_remote_name(cli->conn));
3213 if (tevent_req_nomem(result->desthost, req)) {
3214 return tevent_req_post(req, ev);
3217 result->srv_name_slash = talloc_asprintf_strupper_m(
3218 result, "\\\\%s", result->desthost);
3219 if (tevent_req_nomem(result->srv_name_slash, req)) {
3220 return tevent_req_post(req, ev);
3223 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3225 subreq = rpc_transport_np_init_send(state, ev, cli, table);
3226 if (tevent_req_nomem(subreq, req)) {
3227 return tevent_req_post(req, ev);
3229 tevent_req_set_callback(subreq, rpc_pipe_open_np_done, req);
3233 static void rpc_pipe_open_np_done(struct tevent_req *subreq)
3235 struct tevent_req *req = tevent_req_callback_data(
3236 subreq, struct tevent_req);
3237 struct rpc_pipe_open_np_state *state = tevent_req_data(
3238 req, struct rpc_pipe_open_np_state);
3239 struct rpc_pipe_client *result = state->result;
3240 struct rpc_pipe_client_np_ref *np_ref = NULL;
3243 status = rpc_transport_np_init_recv(
3244 subreq, result, &result->transport);
3245 TALLOC_FREE(subreq);
3246 if (tevent_req_nterror(req, status)) {
3250 result->transport->transport = NCACN_NP;
3252 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3253 if (tevent_req_nomem(np_ref, req)) {
3256 np_ref->cli = state->cli;
3257 np_ref->pipe = result;
3259 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3260 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3262 result->binding_handle = rpccli_bh_create(result, NULL, state->table);
3263 if (tevent_req_nomem(result->binding_handle, req)) {
3267 tevent_req_done(req);
3270 NTSTATUS rpc_pipe_open_np_recv(
3271 struct tevent_req *req,
3272 TALLOC_CTX *mem_ctx,
3273 struct rpc_pipe_client **_result)
3275 struct rpc_pipe_open_np_state *state = tevent_req_data(
3276 req, struct rpc_pipe_open_np_state);
3279 if (tevent_req_is_nterror(req, &status)) {
3282 *_result = talloc_move(mem_ctx, &state->result);
3283 return NT_STATUS_OK;
3286 NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3287 const struct ndr_interface_table *table,
3288 struct rpc_pipe_client **presult)
3290 struct tevent_context *ev = NULL;
3291 struct tevent_req *req = NULL;
3292 NTSTATUS status = NT_STATUS_NO_MEMORY;
3294 ev = samba_tevent_context_init(cli);
3298 req = rpc_pipe_open_np_send(ev, ev, cli, table);
3302 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3305 status = rpc_pipe_open_np_recv(req, NULL, presult);
3312 /****************************************************************************
3313 Open a pipe to a remote server.
3314 ****************************************************************************/
3316 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3317 enum dcerpc_transport_t transport,
3318 const struct ndr_interface_table *table,
3319 const char *remote_name,
3320 const struct sockaddr_storage *remote_sockaddr,
3321 struct rpc_pipe_client **presult)
3323 switch (transport) {
3325 return rpc_pipe_open_tcp(NULL,
3330 return rpc_pipe_open_np(cli, table, presult);
3332 return NT_STATUS_NOT_IMPLEMENTED;
3336 /****************************************************************************
3337 Open a named pipe to an SMB server and bind anonymously.
3338 ****************************************************************************/
3340 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3341 enum dcerpc_transport_t transport,
3342 const struct ndr_interface_table *table,
3343 const char *remote_name,
3344 const struct sockaddr_storage *remote_sockaddr,
3345 struct rpc_pipe_client **presult)
3347 struct rpc_pipe_client *result;
3348 struct pipe_auth_data *auth;
3351 status = cli_rpc_pipe_open(cli,
3357 if (!NT_STATUS_IS_OK(status)) {
3361 status = rpccli_anon_bind_data(result, &auth);
3362 if (!NT_STATUS_IS_OK(status)) {
3363 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3364 nt_errstr(status)));
3365 TALLOC_FREE(result);
3370 * This is a bit of an abstraction violation due to the fact that an
3371 * anonymous bind on an authenticated SMB inherits the user/domain
3372 * from the enclosing SMB creds
3375 if (transport == NCACN_NP) {
3376 struct smbXcli_session *session;
3378 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3379 session = cli->smb2.session;
3381 session = cli->smb1.session;
3384 status = smbXcli_session_application_key(session, auth,
3385 &auth->transport_session_key);
3386 if (!NT_STATUS_IS_OK(status)) {
3387 auth->transport_session_key = data_blob_null;
3391 status = rpc_pipe_bind(result, auth);
3392 if (!NT_STATUS_IS_OK(status)) {
3394 if (ndr_syntax_id_equal(&table->syntax_id,
3395 &ndr_table_dssetup.syntax_id)) {
3396 /* non AD domains just don't have this pipe, avoid
3397 * level 0 statement in that case - gd */
3400 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3401 "%s failed with error %s\n",
3403 nt_errstr(status) ));
3404 TALLOC_FREE(result);
3408 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3409 "%s and bound anonymously.\n",
3414 return NT_STATUS_OK;
3417 /****************************************************************************
3418 ****************************************************************************/
3420 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3421 const struct ndr_interface_table *table,
3422 struct rpc_pipe_client **presult)
3424 const char *remote_name = smbXcli_conn_remote_name(cli->conn);
3425 const struct sockaddr_storage *remote_sockaddr =
3426 smbXcli_conn_remote_sockaddr(cli->conn);
3428 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3435 /****************************************************************************
3436 Open a named pipe to an SMB server and bind using the mech specified
3438 This routine references the creds pointer that is passed in
3439 ****************************************************************************/
3441 NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
3442 const struct ndr_interface_table *table,
3443 enum dcerpc_transport_t transport,
3444 enum dcerpc_AuthType auth_type,
3445 enum dcerpc_AuthLevel auth_level,
3447 const struct sockaddr_storage *remote_sockaddr,
3448 struct cli_credentials *creds,
3449 struct rpc_pipe_client **presult)
3451 struct rpc_pipe_client *result;
3452 struct pipe_auth_data *auth = NULL;
3453 const char *target_service = table->authservices->names[0];
3456 status = cli_rpc_pipe_open(cli,
3462 if (!NT_STATUS_IS_OK(status)) {
3466 status = rpccli_generic_bind_data_from_creds(result,
3467 auth_type, auth_level,
3468 server, target_service,
3471 if (!NT_STATUS_IS_OK(status)) {
3472 DBG_ERR("rpccli_generic_bind_data_from_creds returned %s\n",
3477 status = rpc_pipe_bind(result, auth);
3478 if (!NT_STATUS_IS_OK(status)) {
3479 DBG_ERR("cli_rpc_pipe_bind failed with error %s\n",
3484 DBG_DEBUG("opened pipe %s to machine %s and bound as user %s.\n",
3487 cli_credentials_get_unparsed_name(creds, talloc_tos()));
3490 return NT_STATUS_OK;
3494 TALLOC_FREE(result);
3498 NTSTATUS cli_rpc_pipe_open_bind_schannel(
3499 struct cli_state *cli,
3500 const struct ndr_interface_table *table,
3501 enum dcerpc_transport_t transport,
3502 struct netlogon_creds_cli_context *netlogon_creds,
3503 const char *remote_name,
3504 const struct sockaddr_storage *remote_sockaddr,
3505 struct rpc_pipe_client **_rpccli)
3507 struct rpc_pipe_client *rpccli;
3508 struct pipe_auth_data *rpcauth;
3509 const char *target_service = table->authservices->names[0];
3510 struct cli_credentials *cli_creds;
3511 enum dcerpc_AuthLevel auth_level;
3514 status = cli_rpc_pipe_open(cli,
3520 if (!NT_STATUS_IS_OK(status)) {
3524 auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
3526 status = netlogon_creds_bind_cli_credentials(
3527 netlogon_creds, rpccli, &cli_creds);
3528 if (!NT_STATUS_IS_OK(status)) {
3529 DBG_DEBUG("netlogon_creds_bind_cli_credentials failed: %s\n",
3531 TALLOC_FREE(rpccli);
3535 status = rpccli_generic_bind_data_from_creds(rpccli,
3536 DCERPC_AUTH_TYPE_SCHANNEL,
3542 if (!NT_STATUS_IS_OK(status)) {
3543 DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
3544 nt_errstr(status)));
3545 TALLOC_FREE(rpccli);
3549 status = rpc_pipe_bind(rpccli, rpcauth);
3551 /* No TALLOC_FREE, gensec takes references */
3552 talloc_unlink(rpccli, cli_creds);
3555 if (!NT_STATUS_IS_OK(status)) {
3556 DBG_DEBUG("rpc_pipe_bind failed with error %s\n",
3558 TALLOC_FREE(rpccli);
3564 return NT_STATUS_OK;
3567 NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
3568 const struct ndr_interface_table *table,
3569 enum dcerpc_transport_t transport,
3570 struct netlogon_creds_cli_context *netlogon_creds,
3571 const char *remote_name,
3572 const struct sockaddr_storage *remote_sockaddr,
3573 struct rpc_pipe_client **_rpccli)
3575 TALLOC_CTX *frame = talloc_stackframe();
3576 struct rpc_pipe_client *rpccli;
3577 struct netlogon_creds_cli_lck *lck;
3580 status = netlogon_creds_cli_lck(
3581 netlogon_creds, NETLOGON_CREDS_CLI_LCK_EXCLUSIVE,
3583 if (!NT_STATUS_IS_OK(status)) {
3584 DBG_WARNING("netlogon_creds_cli_lck returned %s\n",
3590 status = cli_rpc_pipe_open_bind_schannel(cli,
3597 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3598 netlogon_creds_cli_delete_lck(netlogon_creds);
3600 if (!NT_STATUS_IS_OK(status)) {
3601 DBG_DEBUG("cli_rpc_pipe_open_bind_schannel failed: %s\n",
3607 if (ndr_syntax_id_equal(&table->syntax_id,
3608 &ndr_table_netlogon.syntax_id)) {
3609 status = netlogon_creds_cli_check(netlogon_creds,
3610 rpccli->binding_handle,
3612 if (!NT_STATUS_IS_OK(status)) {
3613 DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
3614 nt_errstr(status)));
3620 DBG_DEBUG("opened pipe %s to machine %s with key %s "
3621 "and bound using schannel.\n",
3622 table->name, rpccli->desthost,
3623 netlogon_creds_cli_debug_string(netlogon_creds, lck));
3628 return NT_STATUS_OK;
3631 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3632 struct rpc_pipe_client *cli,
3633 DATA_BLOB *session_key)
3636 struct pipe_auth_data *a;
3637 struct gensec_security *gensec_security;
3638 DATA_BLOB sk = { .data = NULL };
3639 bool make_dup = false;
3641 if (!session_key || !cli) {
3642 return NT_STATUS_INVALID_PARAMETER;
3648 return NT_STATUS_INVALID_PARAMETER;
3651 switch (cli->auth->auth_type) {
3652 case DCERPC_AUTH_TYPE_NONE:
3653 sk = data_blob_const(a->transport_session_key.data,
3654 a->transport_session_key.length);
3658 gensec_security = a->auth_ctx;
3659 status = gensec_session_key(gensec_security, mem_ctx, &sk);
3660 if (!NT_STATUS_IS_OK(status)) {
3668 return NT_STATUS_NO_USER_SESSION_KEY;
3672 *session_key = data_blob_dup_talloc(mem_ctx, sk);
3677 return NT_STATUS_OK;