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/rpc/dcerpc.h"
33 #include "librpc/rpc/dcerpc_util.h"
36 #include "libsmb/libsmb.h"
37 #include "auth/gensec/gensec.h"
38 #include "auth/credentials/credentials.h"
39 #include "../libcli/smb/smbXcli_base.h"
42 #define DBGC_CLASS DBGC_RPC_CLI
44 /********************************************************************
45 Pipe description for a DEBUG
46 ********************************************************************/
47 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
48 struct rpc_pipe_client *cli)
50 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
57 /********************************************************************
59 ********************************************************************/
61 static uint32_t get_rpc_call_id(void)
63 static uint32_t call_id = 0;
67 /*******************************************************************
68 Use SMBreadX to get rest of one fragment's worth of rpc data.
69 Reads the whole size or give an error message
70 ********************************************************************/
72 struct rpc_read_state {
73 struct tevent_context *ev;
74 struct rpc_cli_transport *transport;
80 static void rpc_read_done(struct tevent_req *subreq);
82 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
83 struct tevent_context *ev,
84 struct rpc_cli_transport *transport,
85 uint8_t *data, size_t size)
87 struct tevent_req *req, *subreq;
88 struct rpc_read_state *state;
90 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
95 state->transport = transport;
100 DBG_INFO("data_to_read: %zu\n", size);
102 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
104 if (subreq == NULL) {
107 tevent_req_set_callback(subreq, rpc_read_done, req);
115 static void rpc_read_done(struct tevent_req *subreq)
117 struct tevent_req *req = tevent_req_callback_data(
118 subreq, struct tevent_req);
119 struct rpc_read_state *state = tevent_req_data(
120 req, struct rpc_read_state);
124 status = state->transport->read_recv(subreq, &received);
126 if (tevent_req_nterror(req, status)) {
130 state->num_read += received;
131 if (state->num_read == state->size) {
132 tevent_req_done(req);
136 subreq = state->transport->read_send(state, state->ev,
137 state->data + state->num_read,
138 state->size - state->num_read,
139 state->transport->priv);
140 if (tevent_req_nomem(subreq, req)) {
143 tevent_req_set_callback(subreq, rpc_read_done, req);
146 static NTSTATUS rpc_read_recv(struct tevent_req *req)
148 return tevent_req_simple_recv_ntstatus(req);
151 struct rpc_write_state {
152 struct tevent_context *ev;
153 struct rpc_cli_transport *transport;
159 static void rpc_write_done(struct tevent_req *subreq);
161 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
162 struct tevent_context *ev,
163 struct rpc_cli_transport *transport,
164 const uint8_t *data, size_t size)
166 struct tevent_req *req, *subreq;
167 struct rpc_write_state *state;
169 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
174 state->transport = transport;
177 state->num_written = 0;
179 DBG_INFO("data_to_write: %zu\n", size);
181 subreq = transport->write_send(state, ev, data, size, transport->priv);
182 if (tevent_req_nomem(subreq, req)) {
183 return tevent_req_post(req, ev);
185 tevent_req_set_callback(subreq, rpc_write_done, req);
189 static void rpc_write_done(struct tevent_req *subreq)
191 struct tevent_req *req = tevent_req_callback_data(
192 subreq, struct tevent_req);
193 struct rpc_write_state *state = tevent_req_data(
194 req, struct rpc_write_state);
198 status = state->transport->write_recv(subreq, &written);
200 if (tevent_req_nterror(req, status)) {
204 state->num_written += written;
206 if (state->num_written == state->size) {
207 tevent_req_done(req);
211 subreq = state->transport->write_send(state, state->ev,
212 state->data + state->num_written,
213 state->size - state->num_written,
214 state->transport->priv);
215 if (tevent_req_nomem(subreq, req)) {
218 tevent_req_set_callback(subreq, rpc_write_done, req);
221 static NTSTATUS rpc_write_recv(struct tevent_req *req)
223 return tevent_req_simple_recv_ntstatus(req);
227 /****************************************************************************
228 Try and get a PDU's worth of data from current_pdu. If not, then read more
230 ****************************************************************************/
232 struct get_complete_frag_state {
233 struct tevent_context *ev;
234 struct rpc_pipe_client *cli;
239 static void get_complete_frag_got_header(struct tevent_req *subreq);
240 static void get_complete_frag_got_rest(struct tevent_req *subreq);
242 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
243 struct tevent_context *ev,
244 struct rpc_pipe_client *cli,
247 struct tevent_req *req, *subreq;
248 struct get_complete_frag_state *state;
251 req = tevent_req_create(mem_ctx, &state,
252 struct get_complete_frag_state);
258 state->frag_len = RPC_HEADER_LEN;
261 received = pdu->length;
262 if (received < RPC_HEADER_LEN) {
263 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
265 return tevent_req_post(req, ev);
267 subreq = rpc_read_send(state, state->ev,
268 state->cli->transport,
269 pdu->data + received,
270 RPC_HEADER_LEN - received);
271 if (tevent_req_nomem(subreq, req)) {
272 return tevent_req_post(req, ev);
274 tevent_req_set_callback(subreq, get_complete_frag_got_header,
279 state->frag_len = dcerpc_get_frag_length(pdu);
280 if (state->frag_len < RPC_HEADER_LEN) {
281 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
282 return tevent_req_post(req, ev);
285 if (received >= state->frag_len) {
287 * Got the whole fragment
289 tevent_req_done(req);
290 return tevent_req_post(req, ev);
293 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
295 return tevent_req_post(req, ev);
298 subreq = rpc_read_send(
301 state->cli->transport,
302 pdu->data + received,
303 state->frag_len - received);
304 if (tevent_req_nomem(subreq, req)) {
305 return tevent_req_post(req, ev);
307 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
311 static void get_complete_frag_got_header(struct tevent_req *subreq)
313 struct tevent_req *req = tevent_req_callback_data(
314 subreq, struct tevent_req);
315 struct get_complete_frag_state *state = tevent_req_data(
316 req, struct get_complete_frag_state);
319 status = rpc_read_recv(subreq);
321 if (tevent_req_nterror(req, status)) {
325 state->frag_len = dcerpc_get_frag_length(state->pdu);
326 if (state->frag_len < RPC_HEADER_LEN) {
327 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
331 if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
337 * We're here in this piece of code because we've read exactly
338 * RPC_HEADER_LEN bytes into state->pdu.
341 subreq = rpc_read_send(state, state->ev, state->cli->transport,
342 state->pdu->data + RPC_HEADER_LEN,
343 state->frag_len - RPC_HEADER_LEN);
344 if (tevent_req_nomem(subreq, req)) {
347 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
350 static void get_complete_frag_got_rest(struct tevent_req *subreq)
352 NTSTATUS status = rpc_read_recv(subreq);
353 return tevent_req_simple_finish_ntstatus(subreq, status);
356 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
358 return tevent_req_simple_recv_ntstatus(req);
361 /****************************************************************************
362 Do basic authentication checks on an incoming pdu.
363 ****************************************************************************/
365 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
366 struct rpc_pipe_client *cli,
367 struct ncacn_packet *pkt,
369 uint8_t expected_pkt_type,
372 DATA_BLOB *reply_pdu)
374 const struct dcerpc_response *r = NULL;
375 DATA_BLOB tmp_stub = { .data = NULL };
379 * Point the return values at the real data including the RPC
380 * header. Just in case the caller wants it.
384 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
385 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
387 * TODO: do we still need this hack which was introduced
388 * in commit a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0.
390 * I don't even know what AS/U might be...
392 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
393 "fragment first/last ON.\n"));
394 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
397 /* Ensure we have the correct type. */
398 switch (pkt->ptype) {
399 case DCERPC_PKT_BIND_NAK:
400 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
401 rpccli_pipe_txt(talloc_tos(), cli)));
403 ret = dcerpc_verify_ncacn_packet_header(pkt,
405 0, /* max_auth_info */
406 DCERPC_PFC_FLAG_FIRST |
407 DCERPC_PFC_FLAG_LAST,
408 0); /* optional flags */
409 if (!NT_STATUS_IS_OK(ret)) {
410 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
411 "RPC packet type - %u, expected %u: %s\n",
412 rpccli_pipe_txt(talloc_tos(), cli),
413 pkt->ptype, expected_pkt_type,
415 NDR_PRINT_DEBUG(ncacn_packet, pkt);
419 /* Use this for now... */
420 return NT_STATUS_NETWORK_ACCESS_DENIED;
422 case DCERPC_PKT_BIND_ACK:
423 ret = dcerpc_verify_ncacn_packet_header(pkt,
425 pkt->u.bind_ack.auth_info.length,
426 DCERPC_PFC_FLAG_FIRST |
427 DCERPC_PFC_FLAG_LAST,
428 DCERPC_PFC_FLAG_CONC_MPX |
429 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
430 if (!NT_STATUS_IS_OK(ret)) {
431 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
432 "RPC packet type - %u, expected %u: %s\n",
433 rpccli_pipe_txt(talloc_tos(), cli),
434 pkt->ptype, expected_pkt_type,
436 NDR_PRINT_DEBUG(ncacn_packet, pkt);
442 case DCERPC_PKT_ALTER_RESP:
443 ret = dcerpc_verify_ncacn_packet_header(pkt,
445 pkt->u.alter_resp.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_RESPONSE:
464 r = &pkt->u.response;
466 ret = dcerpc_verify_ncacn_packet_header(pkt,
468 r->stub_and_verifier.length,
469 0, /* required_flags */
470 DCERPC_PFC_FLAG_FIRST |
471 DCERPC_PFC_FLAG_LAST);
472 if (!NT_STATUS_IS_OK(ret)) {
473 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
474 "RPC packet type - %u, expected %u: %s\n",
475 rpccli_pipe_txt(talloc_tos(), cli),
476 pkt->ptype, expected_pkt_type,
478 NDR_PRINT_DEBUG(ncacn_packet, pkt);
482 tmp_stub.data = r->stub_and_verifier.data;
483 tmp_stub.length = r->stub_and_verifier.length;
485 /* Here's where we deal with incoming sign/seal. */
486 ret = dcerpc_check_auth(cli->auth, pkt,
488 DCERPC_RESPONSE_LENGTH,
490 if (!NT_STATUS_IS_OK(ret)) {
491 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
492 "RPC packet type - %u, expected %u: %s\n",
493 rpccli_pipe_txt(talloc_tos(), cli),
494 pkt->ptype, expected_pkt_type,
496 NDR_PRINT_DEBUG(ncacn_packet, pkt);
500 /* Point the return values at the NDR data. */
503 DEBUG(10, ("Got pdu len %lu, data_len %lu\n",
504 (long unsigned int)pdu->length,
505 (long unsigned int)rdata->length));
508 * If this is the first reply, and the allocation hint is
509 * reasonable, try and set up the reply_pdu DATA_BLOB to the
513 if ((reply_pdu->length == 0) &&
514 r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
515 if (!data_blob_realloc(mem_ctx, reply_pdu,
517 DEBUG(0, ("reply alloc hint %d too "
518 "large to allocate\n",
519 (int)r->alloc_hint));
520 return NT_STATUS_NO_MEMORY;
526 case DCERPC_PKT_FAULT:
528 ret = dcerpc_verify_ncacn_packet_header(pkt,
530 0, /* max_auth_info */
531 DCERPC_PFC_FLAG_FIRST |
532 DCERPC_PFC_FLAG_LAST,
533 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
534 if (!NT_STATUS_IS_OK(ret)) {
535 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
536 "RPC packet type - %u, expected %u: %s\n",
537 rpccli_pipe_txt(talloc_tos(), cli),
538 pkt->ptype, expected_pkt_type,
540 NDR_PRINT_DEBUG(ncacn_packet, pkt);
544 DEBUG(1, (__location__ ": RPC fault code %s received "
546 dcerpc_errstr(talloc_tos(),
547 pkt->u.fault.status),
548 rpccli_pipe_txt(talloc_tos(), cli)));
550 return dcerpc_fault_to_nt_status(pkt->u.fault.status);
553 DEBUG(0, (__location__ "Unknown packet type %u received "
555 (unsigned int)pkt->ptype,
556 rpccli_pipe_txt(talloc_tos(), cli)));
557 return NT_STATUS_RPC_PROTOCOL_ERROR;
561 if (pkt->call_id != call_id) {
562 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
563 "RPC call_id - %u, not %u\n",
564 rpccli_pipe_txt(talloc_tos(), cli),
565 pkt->call_id, call_id));
566 return NT_STATUS_RPC_PROTOCOL_ERROR;
572 /****************************************************************************
573 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
574 ****************************************************************************/
576 struct cli_api_pipe_state {
577 struct tevent_context *ev;
578 struct rpc_cli_transport *transport;
583 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
584 static void cli_api_pipe_write_done(struct tevent_req *subreq);
585 static void cli_api_pipe_read_done(struct tevent_req *subreq);
587 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
588 struct tevent_context *ev,
589 struct rpc_cli_transport *transport,
590 uint8_t *data, size_t data_len,
591 uint32_t max_rdata_len)
593 struct tevent_req *req, *subreq;
594 struct cli_api_pipe_state *state;
597 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
602 state->transport = transport;
604 if (max_rdata_len < RPC_HEADER_LEN) {
606 * For a RPC reply we always need at least RPC_HEADER_LEN
607 * bytes. We check this here because we will receive
608 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
610 status = NT_STATUS_INVALID_PARAMETER;
614 if (transport->trans_send != NULL) {
615 subreq = transport->trans_send(state, ev, data, data_len,
616 max_rdata_len, transport->priv);
617 if (subreq == NULL) {
620 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
625 * If the transport does not provide a "trans" routine, i.e. for
626 * example the ncacn_ip_tcp transport, do the write/read step here.
629 subreq = rpc_write_send(state, ev, transport, data, data_len);
630 if (subreq == NULL) {
633 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
637 tevent_req_nterror(req, status);
638 return tevent_req_post(req, ev);
644 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
646 struct tevent_req *req = tevent_req_callback_data(
647 subreq, struct tevent_req);
648 struct cli_api_pipe_state *state = tevent_req_data(
649 req, struct cli_api_pipe_state);
652 status = state->transport->trans_recv(subreq, state, &state->rdata,
655 if (tevent_req_nterror(req, status)) {
658 tevent_req_done(req);
661 static void cli_api_pipe_write_done(struct tevent_req *subreq)
663 struct tevent_req *req = tevent_req_callback_data(
664 subreq, struct tevent_req);
665 struct cli_api_pipe_state *state = tevent_req_data(
666 req, struct cli_api_pipe_state);
669 status = rpc_write_recv(subreq);
671 if (tevent_req_nterror(req, status)) {
675 state->rdata = talloc_array(state, uint8_t, RPC_HEADER_LEN);
676 if (tevent_req_nomem(state->rdata, req)) {
681 * We don't need to use rpc_read_send here, the upper layer will cope
682 * with a short read, transport->trans_send could also return less
683 * than state->max_rdata_len.
685 subreq = state->transport->read_send(state, state->ev, state->rdata,
687 state->transport->priv);
688 if (tevent_req_nomem(subreq, req)) {
691 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
694 static void cli_api_pipe_read_done(struct tevent_req *subreq)
696 struct tevent_req *req = tevent_req_callback_data(
697 subreq, struct tevent_req);
698 struct cli_api_pipe_state *state = tevent_req_data(
699 req, struct cli_api_pipe_state);
703 status = state->transport->read_recv(subreq, &received);
705 if (tevent_req_nterror(req, status)) {
708 state->rdata_len = received;
709 tevent_req_done(req);
712 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
713 uint8_t **prdata, uint32_t *prdata_len)
715 struct cli_api_pipe_state *state = tevent_req_data(
716 req, struct cli_api_pipe_state);
719 if (tevent_req_is_nterror(req, &status)) {
723 *prdata = talloc_move(mem_ctx, &state->rdata);
724 *prdata_len = state->rdata_len;
728 /****************************************************************************
729 Send data on an rpc pipe via trans. The data must be the last
730 pdu fragment of an NDR data stream.
732 Receive response data from an rpc pipe, which may be large...
734 Read the first fragment: unfortunately have to use SMBtrans for the first
735 bit, then SMBreadX for subsequent bits.
737 If first fragment received also wasn't the last fragment, continue
738 getting fragments until we _do_ receive the last fragment.
740 Request/Response PDU's look like the following...
742 |<------------------PDU len----------------------------------------------->|
743 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
745 +------------+-----------------+-------------+---------------+-------------+
746 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
747 +------------+-----------------+-------------+---------------+-------------+
749 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
750 signing & sealing being negotiated.
752 ****************************************************************************/
754 struct rpc_api_pipe_state {
755 struct tevent_context *ev;
756 struct rpc_pipe_client *cli;
757 uint8_t expected_pkt_type;
760 DATA_BLOB incoming_frag;
761 struct ncacn_packet *pkt;
765 size_t reply_pdu_offset;
769 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
770 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
771 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq);
773 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
774 struct tevent_context *ev,
775 struct rpc_pipe_client *cli,
776 DATA_BLOB *data, /* Outgoing PDU */
777 uint8_t expected_pkt_type,
780 struct tevent_req *req, *subreq;
781 struct rpc_api_pipe_state *state;
782 uint16_t max_recv_frag;
784 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
790 state->expected_pkt_type = expected_pkt_type;
791 state->call_id = call_id;
792 state->endianess = DCERPC_DREP_LE;
795 * Ensure we're not sending too much.
797 if (data->length > cli->max_xmit_frag) {
798 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
799 return tevent_req_post(req, ev);
802 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
804 if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
805 subreq = rpc_write_send(state, ev, cli->transport,
806 data->data, data->length);
807 if (tevent_req_nomem(subreq, req)) {
808 return tevent_req_post(req, ev);
810 tevent_req_set_callback(subreq, rpc_api_pipe_auth3_done, req);
814 /* get the header first, then fetch the rest once we have
815 * the frag_length available */
816 max_recv_frag = RPC_HEADER_LEN;
818 subreq = cli_api_pipe_send(state, ev, cli->transport,
819 data->data, data->length, max_recv_frag);
820 if (tevent_req_nomem(subreq, req)) {
821 return tevent_req_post(req, ev);
823 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
827 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq)
829 NTSTATUS status = rpc_write_recv(subreq);
830 return tevent_req_simple_finish_ntstatus(subreq, status);
833 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
835 struct tevent_req *req = tevent_req_callback_data(
836 subreq, struct tevent_req);
837 struct rpc_api_pipe_state *state = tevent_req_data(
838 req, struct rpc_api_pipe_state);
840 uint8_t *rdata = NULL;
841 uint32_t rdata_len = 0;
843 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
845 if (tevent_req_nterror(req, status)) {;
846 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
851 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
852 rpccli_pipe_txt(talloc_tos(), state->cli)));
853 tevent_req_done(req);
858 * Move data on state->incoming_frag.
860 state->incoming_frag.data = talloc_move(state, &rdata);
861 state->incoming_frag.length = rdata_len;
862 if (!state->incoming_frag.data) {
863 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
867 /* Ensure we have enough data for a pdu. */
868 subreq = get_complete_frag_send(state, state->ev, state->cli,
869 &state->incoming_frag);
870 if (tevent_req_nomem(subreq, req)) {
873 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
876 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
878 struct tevent_req *req = tevent_req_callback_data(
879 subreq, struct tevent_req);
880 struct rpc_api_pipe_state *state = tevent_req_data(
881 req, struct rpc_api_pipe_state);
883 DATA_BLOB rdata = { .data = NULL };
885 status = get_complete_frag_recv(subreq);
887 if (tevent_req_nterror(req, status)) {
888 DEBUG(5, ("get_complete_frag failed: %s\n",
893 state->pkt = talloc(state, struct ncacn_packet);
896 * TODO: do a real async disconnect ...
898 * For now do it sync...
900 TALLOC_FREE(state->cli->transport);
905 status = dcerpc_pull_ncacn_packet(state->pkt,
906 &state->incoming_frag,
908 if (tevent_req_nterror(req, status)) {
910 * TODO: do a real async disconnect ...
912 * For now do it sync...
914 TALLOC_FREE(state->cli->transport);
918 if (DEBUGLEVEL >= 10) {
919 NDR_PRINT_DEBUG(ncacn_packet, state->pkt);
922 status = cli_pipe_validate_current_pdu(state,
923 state->cli, state->pkt,
924 &state->incoming_frag,
925 state->expected_pkt_type,
930 DBG_DEBUG("got frag len of %zu at offset %zu: %s\n",
931 state->incoming_frag.length,
932 state->reply_pdu_offset,
935 if (state->pkt->ptype != DCERPC_PKT_FAULT && !NT_STATUS_IS_OK(status)) {
937 * TODO: do a real async disconnect ...
939 * For now do it sync...
941 TALLOC_FREE(state->cli->transport);
942 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
944 * TODO: do a real async disconnect ...
946 * For now do it sync...
948 TALLOC_FREE(state->cli->transport);
949 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
951 * TODO: do a real async disconnect ...
953 * For now do it sync...
955 TALLOC_FREE(state->cli->transport);
957 if (tevent_req_nterror(req, status)) {
961 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
962 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
964 * Set the data type correctly for big-endian data on the
967 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
969 rpccli_pipe_txt(talloc_tos(), state->cli)));
970 state->endianess = 0x00; /* BIG ENDIAN */
973 * Check endianness on subsequent packets.
975 if (state->endianess != state->pkt->drep[0]) {
976 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
978 state->endianess?"little":"big",
979 state->pkt->drep[0]?"little":"big"));
981 * TODO: do a real async disconnect ...
983 * For now do it sync...
985 TALLOC_FREE(state->cli->transport);
986 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
990 if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) {
992 * TODO: do a real async disconnect ...
994 * For now do it sync...
996 TALLOC_FREE(state->cli->transport);
997 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1001 /* Now copy the data portion out of the pdu into rbuf. */
1002 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
1003 if (!data_blob_realloc(NULL, &state->reply_pdu,
1004 state->reply_pdu_offset + rdata.length)) {
1006 * TODO: do a real async disconnect ...
1008 * For now do it sync...
1010 TALLOC_FREE(state->cli->transport);
1011 tevent_req_oom(req);
1016 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
1017 rdata.data, rdata.length);
1018 state->reply_pdu_offset += rdata.length;
1020 /* reset state->incoming_frag, there is no need to free it,
1021 * it will be reallocated to the right size the next time
1023 state->incoming_frag.length = 0;
1025 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1026 /* make sure the pdu length is right now that we
1027 * have all the data available (alloc hint may
1028 * have allocated more than was actually used) */
1029 state->reply_pdu.length = state->reply_pdu_offset;
1030 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1031 rpccli_pipe_txt(talloc_tos(), state->cli),
1032 (unsigned)state->reply_pdu.length));
1033 tevent_req_done(req);
1037 subreq = get_complete_frag_send(state, state->ev, state->cli,
1038 &state->incoming_frag);
1039 if (subreq == NULL) {
1041 * TODO: do a real async disconnect ...
1043 * For now do it sync...
1045 TALLOC_FREE(state->cli->transport);
1047 if (tevent_req_nomem(subreq, req)) {
1050 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1053 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1054 struct ncacn_packet **pkt,
1055 DATA_BLOB *reply_pdu)
1057 struct rpc_api_pipe_state *state = tevent_req_data(
1058 req, struct rpc_api_pipe_state);
1061 if (tevent_req_is_nterror(req, &status)) {
1065 /* return data to caller and assign it ownership of memory */
1067 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1068 reply_pdu->length = state->reply_pdu.length;
1069 state->reply_pdu.length = 0;
1071 data_blob_free(&state->reply_pdu);
1075 *pkt = talloc_steal(mem_ctx, state->pkt);
1078 return NT_STATUS_OK;
1081 /*******************************************************************
1082 Creates NTLMSSP auth bind.
1083 ********************************************************************/
1085 static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1086 TALLOC_CTX *mem_ctx,
1087 DATA_BLOB *auth_token,
1088 bool *client_hdr_signing)
1090 struct gensec_security *gensec_security;
1091 DATA_BLOB null_blob = { .data = NULL };
1094 gensec_security = cli->auth->auth_ctx;
1096 DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
1097 status = gensec_update(gensec_security, mem_ctx, null_blob, auth_token);
1099 if (!NT_STATUS_IS_OK(status) &&
1100 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1105 if (client_hdr_signing == NULL) {
1109 if (cli->auth->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1110 *client_hdr_signing = false;
1114 *client_hdr_signing = gensec_have_feature(gensec_security,
1115 GENSEC_FEATURE_SIGN_PKT_HEADER);
1120 /*******************************************************************
1121 Creates the internals of a DCE/RPC bind request or alter context PDU.
1122 ********************************************************************/
1124 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1125 enum dcerpc_pkt_type ptype,
1126 uint32_t rpc_call_id,
1127 const struct ndr_syntax_id *abstract,
1128 const struct ndr_syntax_id *transfer,
1129 const DATA_BLOB *auth_info,
1130 bool client_hdr_signing,
1133 uint16_t auth_len = auth_info->length;
1135 struct dcerpc_ctx_list ctx_list = {
1137 .num_transfer_syntaxes = 1,
1138 .abstract_syntax = *abstract,
1139 .transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer),
1141 union dcerpc_payload u = {
1142 .bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN,
1143 .bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN,
1144 .bind.num_contexts = 1,
1145 .bind.ctx_list = &ctx_list,
1146 .bind.auth_info = *auth_info,
1148 uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1151 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1154 if (client_hdr_signing) {
1155 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1158 status = dcerpc_push_ncacn_packet(mem_ctx,
1164 if (!NT_STATUS_IS_OK(status)) {
1165 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1169 return NT_STATUS_OK;
1172 /*******************************************************************
1173 Creates a DCE/RPC bind request.
1174 ********************************************************************/
1176 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1177 struct rpc_pipe_client *cli,
1178 struct pipe_auth_data *auth,
1179 uint32_t rpc_call_id,
1180 const struct ndr_syntax_id *abstract,
1181 const struct ndr_syntax_id *transfer,
1184 DATA_BLOB auth_token = { .data = NULL };
1185 DATA_BLOB auth_info = { .data = NULL };
1188 if (auth->auth_type != DCERPC_AUTH_TYPE_NONE) {
1189 ret = create_generic_auth_rpc_bind_req(
1190 cli, mem_ctx, &auth_token, &auth->client_hdr_signing);
1192 if (!NT_STATUS_IS_OK(ret) &&
1193 !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1198 if (auth_token.length != 0) {
1199 ret = dcerpc_push_dcerpc_auth(cli,
1202 0, /* auth_pad_length */
1203 auth->auth_context_id,
1206 if (!NT_STATUS_IS_OK(ret)) {
1209 data_blob_free(&auth_token);
1212 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1218 auth->client_hdr_signing,
1220 data_blob_free(&auth_info);
1225 /*******************************************************************
1227 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1228 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1229 and deals with signing/sealing details.
1230 ********************************************************************/
1232 struct rpc_api_pipe_req_state {
1233 struct tevent_context *ev;
1234 struct rpc_pipe_client *cli;
1237 const DATA_BLOB *req_data;
1238 const struct GUID *object_uuid;
1239 uint32_t req_data_sent;
1240 DATA_BLOB req_trailer;
1241 uint32_t req_trailer_sent;
1242 bool verify_bitmask1;
1243 bool verify_pcontext;
1245 DATA_BLOB reply_pdu;
1248 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1249 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1250 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state);
1251 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1252 bool *is_last_frag);
1254 static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1255 struct tevent_context *ev,
1256 struct rpc_pipe_client *cli,
1258 const struct GUID *object_uuid,
1259 const DATA_BLOB *req_data)
1261 struct tevent_req *req, *subreq;
1262 struct rpc_api_pipe_req_state *state;
1266 req = tevent_req_create(mem_ctx, &state,
1267 struct rpc_api_pipe_req_state);
1273 state->op_num = op_num;
1274 state->object_uuid = object_uuid;
1275 state->req_data = req_data;
1276 state->call_id = get_rpc_call_id();
1278 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1279 + RPC_MAX_SIGN_SIZE) {
1280 /* Server is screwed up ! */
1281 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1282 return tevent_req_post(req, ev);
1285 status = prepare_verification_trailer(state);
1286 if (tevent_req_nterror(req, status)) {
1287 return tevent_req_post(req, ev);
1290 status = prepare_next_frag(state, &is_last_frag);
1291 if (tevent_req_nterror(req, status)) {
1292 return tevent_req_post(req, ev);
1296 subreq = rpc_api_pipe_send(state, ev, state->cli,
1298 DCERPC_PKT_RESPONSE,
1300 if (tevent_req_nomem(subreq, req)) {
1301 return tevent_req_post(req, ev);
1303 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1305 subreq = rpc_write_send(state, ev, cli->transport,
1306 state->rpc_out.data,
1307 state->rpc_out.length);
1308 if (tevent_req_nomem(subreq, req)) {
1309 return tevent_req_post(req, ev);
1311 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1317 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state)
1319 struct pipe_auth_data *a = state->cli->auth;
1320 struct dcerpc_sec_verification_trailer *t;
1321 struct ndr_push *ndr = NULL;
1322 enum ndr_err_code ndr_err;
1327 return NT_STATUS_OK;
1330 if (a->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1331 return NT_STATUS_OK;
1334 t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1336 return NT_STATUS_NO_MEMORY;
1339 if (!a->verified_bitmask1) {
1340 t->commands = talloc_realloc(t, t->commands,
1341 struct dcerpc_sec_vt,
1342 t->count.count + 1);
1343 if (t->commands == NULL) {
1344 return NT_STATUS_NO_MEMORY;
1346 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
1347 .command = DCERPC_SEC_VT_COMMAND_BITMASK1,
1348 .u.bitmask1 = (a->client_hdr_signing) ?
1349 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING :
1352 state->verify_bitmask1 = true;
1355 if (!state->cli->verified_pcontext) {
1356 t->commands = talloc_realloc(t, t->commands,
1357 struct dcerpc_sec_vt,
1358 t->count.count + 1);
1359 if (t->commands == NULL) {
1360 return NT_STATUS_NO_MEMORY;
1362 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
1363 .command = DCERPC_SEC_VT_COMMAND_PCONTEXT,
1364 .u.pcontext.abstract_syntax =
1365 state->cli->abstract_syntax,
1366 .u.pcontext.transfer_syntax =
1367 state->cli->transfer_syntax,
1369 state->verify_pcontext = true;
1372 if (!a->hdr_signing) {
1373 t->commands = talloc_realloc(t, t->commands,
1374 struct dcerpc_sec_vt,
1375 t->count.count + 1);
1376 if (t->commands == NULL) {
1377 return NT_STATUS_NO_MEMORY;
1379 t->commands[t->count.count++] = (struct dcerpc_sec_vt) {
1380 .command = DCERPC_SEC_VT_COMMAND_HEADER2,
1381 .u.header2.ptype = DCERPC_PKT_REQUEST,
1382 .u.header2.drep[0] = DCERPC_DREP_LE,
1383 .u.header2.call_id = state->call_id,
1384 .u.header2.context_id = 0,
1385 .u.header2.opnum = state->op_num,
1389 if (t->count.count == 0) {
1391 return NT_STATUS_OK;
1394 t->commands[t->count.count - 1].command |= DCERPC_SEC_VT_COMMAND_END;
1396 if (DEBUGLEVEL >= 10) {
1397 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1400 ndr = ndr_push_init_ctx(state);
1402 return NT_STATUS_NO_MEMORY;
1405 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1406 NDR_SCALARS | NDR_BUFFERS,
1409 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1410 return ndr_map_error2ntstatus(ndr_err);
1412 state->req_trailer = ndr_push_blob(ndr);
1414 align = state->req_data->length & 0x3;
1421 const uint8_t zeros[4] = { 0, };
1423 ok = data_blob_append(ndr, &state->req_trailer, zeros, pad);
1425 return NT_STATUS_NO_MEMORY;
1428 /* move the padding to the start */
1429 p = state->req_trailer.data;
1430 memmove(p + pad, p, state->req_trailer.length - pad);
1434 return NT_STATUS_OK;
1437 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1445 size_t data_thistime;
1446 size_t trailer_left;
1447 size_t trailer_thistime = 0;
1449 size_t total_thistime;
1452 union dcerpc_payload u;
1454 data_left = state->req_data->length - state->req_data_sent;
1455 trailer_left = state->req_trailer.length - state->req_trailer_sent;
1456 total_left = data_left + trailer_left;
1457 if ((total_left < data_left) || (total_left < trailer_left)) {
1461 return NT_STATUS_INVALID_PARAMETER_MIX;
1464 status = dcerpc_guess_sizes(state->cli->auth,
1465 DCERPC_REQUEST_LENGTH, total_left,
1466 state->cli->max_xmit_frag,
1468 &frag_len, &auth_len, &pad_len);
1469 if (!NT_STATUS_IS_OK(status)) {
1473 if (state->req_data_sent == 0) {
1474 flags = DCERPC_PFC_FLAG_FIRST;
1477 if (total_thistime == total_left) {
1478 flags |= DCERPC_PFC_FLAG_LAST;
1481 data_thistime = MIN(total_thistime, data_left);
1482 if (data_thistime < total_thistime) {
1483 trailer_thistime = total_thistime - data_thistime;
1486 data_blob_free(&state->rpc_out);
1488 u = (union dcerpc_payload) {
1489 .request.alloc_hint = total_left,
1490 .request.context_id = 0,
1491 .request.opnum = state->op_num,
1494 if (state->object_uuid) {
1495 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1496 u.request.object.object = *state->object_uuid;
1497 frag_len += ndr_size_GUID(state->object_uuid, 0);
1500 status = dcerpc_push_ncacn_packet(state,
1507 if (!NT_STATUS_IS_OK(status)) {
1511 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1512 * compute it right for requests because the auth trailer is missing
1514 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1516 if (data_thistime > 0) {
1517 /* Copy in the data. */
1518 ok = data_blob_append(NULL, &state->rpc_out,
1519 state->req_data->data + state->req_data_sent,
1522 return NT_STATUS_NO_MEMORY;
1524 state->req_data_sent += data_thistime;
1527 if (trailer_thistime > 0) {
1528 /* Copy in the verification trailer. */
1529 ok = data_blob_append(NULL, &state->rpc_out,
1530 state->req_trailer.data + state->req_trailer_sent,
1533 return NT_STATUS_NO_MEMORY;
1535 state->req_trailer_sent += trailer_thistime;
1538 switch (state->cli->auth->auth_level) {
1539 case DCERPC_AUTH_LEVEL_NONE:
1540 case DCERPC_AUTH_LEVEL_CONNECT:
1542 case DCERPC_AUTH_LEVEL_PACKET:
1543 case DCERPC_AUTH_LEVEL_INTEGRITY:
1544 case DCERPC_AUTH_LEVEL_PRIVACY:
1545 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1547 if (!NT_STATUS_IS_OK(status)) {
1552 return NT_STATUS_INVALID_PARAMETER;
1555 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1560 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1562 struct tevent_req *req = tevent_req_callback_data(
1563 subreq, struct tevent_req);
1564 struct rpc_api_pipe_req_state *state = tevent_req_data(
1565 req, struct rpc_api_pipe_req_state);
1569 status = rpc_write_recv(subreq);
1570 TALLOC_FREE(subreq);
1571 if (tevent_req_nterror(req, status)) {
1575 status = prepare_next_frag(state, &is_last_frag);
1576 if (tevent_req_nterror(req, status)) {
1581 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1583 DCERPC_PKT_RESPONSE,
1585 if (tevent_req_nomem(subreq, req)) {
1588 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1590 subreq = rpc_write_send(state, state->ev,
1591 state->cli->transport,
1592 state->rpc_out.data,
1593 state->rpc_out.length);
1594 if (tevent_req_nomem(subreq, req)) {
1597 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1602 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1604 struct tevent_req *req = tevent_req_callback_data(
1605 subreq, struct tevent_req);
1606 struct rpc_api_pipe_req_state *state = tevent_req_data(
1607 req, struct rpc_api_pipe_req_state);
1610 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1611 TALLOC_FREE(subreq);
1612 if (tevent_req_nterror(req, status)) {
1616 if (state->cli->auth == NULL) {
1617 tevent_req_done(req);
1621 if (state->verify_bitmask1) {
1622 state->cli->auth->verified_bitmask1 = true;
1625 if (state->verify_pcontext) {
1626 state->cli->verified_pcontext = true;
1629 tevent_req_done(req);
1632 static NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1633 DATA_BLOB *reply_pdu)
1635 struct rpc_api_pipe_req_state *state = tevent_req_data(
1636 req, struct rpc_api_pipe_req_state);
1639 if (tevent_req_is_nterror(req, &status)) {
1641 * We always have to initialize to reply pdu, even if there is
1642 * none. The rpccli_* caller routines expect this.
1644 *reply_pdu = data_blob_null;
1648 /* return data to caller and assign it ownership of memory */
1649 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1650 reply_pdu->length = state->reply_pdu.length;
1651 state->reply_pdu.length = 0;
1653 return NT_STATUS_OK;
1656 /****************************************************************************
1657 Check the rpc bind acknowledge response.
1658 ****************************************************************************/
1660 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1661 const struct ndr_syntax_id *transfer)
1663 struct dcerpc_ack_ctx ctx;
1666 if (r->secondary_address_size == 0) {
1667 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1670 if (r->num_results < 1 || !r->ctx_list) {
1674 ctx = r->ctx_list[0];
1676 /* check the transfer syntax */
1677 equal = ndr_syntax_id_equal(&ctx.syntax, transfer);
1679 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1683 if (r->num_results != 0x1 || ctx.result != 0) {
1684 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1685 r->num_results, ctx.reason.value));
1688 DEBUG(5,("check_bind_response: accepted!\n"));
1692 /*******************************************************************
1693 Creates a DCE/RPC bind authentication response.
1694 This is the packet that is sent back to the server once we
1695 have received a BIND-ACK, to finish the third leg of
1696 the authentication handshake.
1697 ********************************************************************/
1699 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1700 struct rpc_pipe_client *cli,
1701 struct pipe_auth_data *auth,
1702 uint32_t rpc_call_id,
1703 DATA_BLOB *pauth_blob,
1707 union dcerpc_payload u = { .auth3._pad = 0, };
1709 status = dcerpc_push_dcerpc_auth(mem_ctx,
1712 0, /* auth_pad_length */
1713 auth->auth_context_id,
1715 &u.auth3.auth_info);
1716 if (!NT_STATUS_IS_OK(status)) {
1720 status = dcerpc_push_ncacn_packet(mem_ctx,
1722 DCERPC_PFC_FLAG_FIRST |
1723 DCERPC_PFC_FLAG_LAST,
1728 data_blob_free(&u.auth3.auth_info);
1729 if (!NT_STATUS_IS_OK(status)) {
1730 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1734 return NT_STATUS_OK;
1737 /*******************************************************************
1738 Creates a DCE/RPC bind alter context authentication request which
1739 may contain a spnego auth blob
1740 ********************************************************************/
1742 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1743 struct pipe_auth_data *auth,
1744 uint32_t rpc_call_id,
1745 const struct ndr_syntax_id *abstract,
1746 const struct ndr_syntax_id *transfer,
1747 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1750 DATA_BLOB auth_info;
1753 status = dcerpc_push_dcerpc_auth(mem_ctx,
1756 0, /* auth_pad_length */
1757 auth->auth_context_id,
1760 if (!NT_STATUS_IS_OK(status)) {
1764 status = create_bind_or_alt_ctx_internal(mem_ctx,
1770 false, /* client_hdr_signing */
1772 data_blob_free(&auth_info);
1776 /****************************************************************************
1778 ****************************************************************************/
1780 struct rpc_pipe_bind_state {
1781 struct tevent_context *ev;
1782 struct rpc_pipe_client *cli;
1785 uint32_t rpc_call_id;
1788 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1789 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1790 struct rpc_pipe_bind_state *state,
1791 DATA_BLOB *credentials);
1792 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1793 struct rpc_pipe_bind_state *state,
1794 DATA_BLOB *credentials);
1796 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1797 struct tevent_context *ev,
1798 struct rpc_pipe_client *cli,
1799 struct pipe_auth_data *auth)
1801 struct tevent_req *req, *subreq;
1802 struct rpc_pipe_bind_state *state;
1805 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1810 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1811 rpccli_pipe_txt(talloc_tos(), cli),
1812 (unsigned int)auth->auth_type,
1813 (unsigned int)auth->auth_level ));
1817 state->rpc_call_id = get_rpc_call_id();
1819 cli->auth = talloc_move(cli, &auth);
1821 /* Marshall the outgoing data. */
1822 status = create_rpc_bind_req(state, cli,
1825 &cli->abstract_syntax,
1826 &cli->transfer_syntax,
1829 if (!NT_STATUS_IS_OK(status) &&
1830 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1831 tevent_req_nterror(req, status);
1832 return tevent_req_post(req, ev);
1835 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1836 DCERPC_PKT_BIND_ACK, state->rpc_call_id);
1837 if (tevent_req_nomem(subreq, req)) {
1838 return tevent_req_post(req, ev);
1840 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1844 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1846 struct tevent_req *req = tevent_req_callback_data(
1847 subreq, struct tevent_req);
1848 struct rpc_pipe_bind_state *state = tevent_req_data(
1849 req, struct rpc_pipe_bind_state);
1850 struct pipe_auth_data *pauth = state->cli->auth;
1851 struct gensec_security *gensec_security;
1852 struct ncacn_packet *pkt = NULL;
1853 struct dcerpc_auth auth;
1854 DATA_BLOB auth_token = { .data = NULL };
1857 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
1858 TALLOC_FREE(subreq);
1859 if (tevent_req_nterror(req, status)) {
1860 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1861 rpccli_pipe_txt(talloc_tos(), state->cli),
1862 nt_errstr(status)));
1867 tevent_req_done(req);
1871 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1872 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1873 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1877 if (pkt->ptype == DCERPC_PKT_BIND_ACK) {
1878 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1879 if (pauth->client_hdr_signing) {
1880 pauth->hdr_signing = true;
1885 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1887 if (pauth->auth_type == DCERPC_AUTH_TYPE_NONE) {
1888 /* Bind complete. */
1889 tevent_req_done(req);
1893 if (pkt->auth_length == 0) {
1894 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1898 /* get auth credentials */
1899 status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
1900 &pkt->u.bind_ack.auth_info,
1902 if (tevent_req_nterror(req, status)) {
1903 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1904 nt_errstr(status)));
1908 if (auth.auth_type != pauth->auth_type) {
1909 DBG_ERR("Auth type %u mismatch expected %u.\n",
1910 auth.auth_type, pauth->auth_type);
1911 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1915 if (auth.auth_level != pauth->auth_level) {
1916 DBG_ERR("Auth level %u mismatch expected %u.\n",
1917 auth.auth_level, pauth->auth_level);
1918 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1922 if (auth.auth_context_id != pauth->auth_context_id) {
1923 DBG_ERR("Auth context id %"PRIu32" mismatch "
1924 "expected %"PRIu32".\n",
1925 auth.auth_context_id,
1926 pauth->auth_context_id);
1927 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1932 * For authenticated binds we may need to do 3 or 4 leg binds.
1935 if (pauth->auth_type == DCERPC_AUTH_TYPE_NONE) {
1936 /* Bind complete. */
1937 tevent_req_done(req);
1941 gensec_security = pauth->auth_ctx;
1943 status = gensec_update(gensec_security, state,
1944 auth.credentials, &auth_token);
1945 if (NT_STATUS_EQUAL(status,
1946 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1947 status = rpc_bind_next_send(req, state,
1949 } else if (NT_STATUS_IS_OK(status)) {
1950 if (pauth->hdr_signing) {
1951 gensec_want_feature(gensec_security,
1952 GENSEC_FEATURE_SIGN_PKT_HEADER);
1955 if (auth_token.length == 0) {
1956 /* Bind complete. */
1957 tevent_req_done(req);
1960 status = rpc_bind_finish_send(req, state,
1964 if (!NT_STATUS_IS_OK(status)) {
1965 tevent_req_nterror(req, status);
1970 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1971 struct rpc_pipe_bind_state *state,
1972 DATA_BLOB *auth_token)
1974 struct pipe_auth_data *auth = state->cli->auth;
1975 struct tevent_req *subreq;
1978 /* Now prepare the alter context pdu. */
1979 data_blob_free(&state->rpc_out);
1981 status = create_rpc_alter_context(state, auth,
1983 &state->cli->abstract_syntax,
1984 &state->cli->transfer_syntax,
1987 if (!NT_STATUS_IS_OK(status)) {
1991 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1992 &state->rpc_out, DCERPC_PKT_ALTER_RESP,
1993 state->rpc_call_id);
1994 if (subreq == NULL) {
1995 return NT_STATUS_NO_MEMORY;
1997 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1998 return NT_STATUS_OK;
2001 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
2002 struct rpc_pipe_bind_state *state,
2003 DATA_BLOB *auth_token)
2005 struct pipe_auth_data *auth = state->cli->auth;
2006 struct tevent_req *subreq;
2009 state->auth3 = true;
2011 /* Now prepare the auth3 context pdu. */
2012 data_blob_free(&state->rpc_out);
2014 status = create_rpc_bind_auth3(state, state->cli, auth,
2018 if (!NT_STATUS_IS_OK(status)) {
2022 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2023 &state->rpc_out, DCERPC_PKT_AUTH3,
2024 state->rpc_call_id);
2025 if (subreq == NULL) {
2026 return NT_STATUS_NO_MEMORY;
2028 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2029 return NT_STATUS_OK;
2032 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2034 return tevent_req_simple_recv_ntstatus(req);
2037 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2038 struct pipe_auth_data *auth)
2040 TALLOC_CTX *frame = talloc_stackframe();
2041 struct tevent_context *ev;
2042 struct tevent_req *req;
2043 NTSTATUS status = NT_STATUS_OK;
2045 ev = samba_tevent_context_init(frame);
2047 status = NT_STATUS_NO_MEMORY;
2051 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2053 status = NT_STATUS_NO_MEMORY;
2057 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2061 status = rpc_pipe_bind_recv(req);
2067 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2069 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2070 unsigned int timeout)
2072 if (rpc_cli == NULL) {
2073 return RPCCLI_DEFAULT_TIMEOUT;
2076 if (rpc_cli->binding_handle == NULL) {
2077 return RPCCLI_DEFAULT_TIMEOUT;
2080 return dcerpc_binding_handle_set_timeout(rpc_cli->binding_handle,
2084 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2086 if (rpc_cli == NULL) {
2090 if (rpc_cli->binding_handle == NULL) {
2094 return dcerpc_binding_handle_is_connected(rpc_cli->binding_handle);
2097 struct rpccli_bh_state {
2098 struct rpc_pipe_client *rpc_cli;
2101 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2103 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2104 struct rpccli_bh_state);
2105 struct rpc_cli_transport *transport = hs->rpc_cli->transport;
2107 if (transport == NULL) {
2111 if (transport->is_connected == NULL) {
2115 return transport->is_connected(transport->priv);
2118 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2121 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2122 struct rpccli_bh_state);
2123 struct rpc_cli_transport *transport = hs->rpc_cli->transport;
2126 if (transport == NULL) {
2127 return RPCCLI_DEFAULT_TIMEOUT;
2130 if (transport->set_timeout == NULL) {
2131 return RPCCLI_DEFAULT_TIMEOUT;
2134 old = transport->set_timeout(transport->priv, timeout);
2136 return RPCCLI_DEFAULT_TIMEOUT;
2142 static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
2143 enum dcerpc_AuthType *auth_type,
2144 enum dcerpc_AuthLevel *auth_level)
2146 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2147 struct rpccli_bh_state);
2149 if (hs->rpc_cli == NULL) {
2153 if (hs->rpc_cli->auth == NULL) {
2157 *auth_type = hs->rpc_cli->auth->auth_type;
2158 *auth_level = hs->rpc_cli->auth->auth_level;
2161 struct rpccli_bh_raw_call_state {
2167 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2169 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2170 struct tevent_context *ev,
2171 struct dcerpc_binding_handle *h,
2172 const struct GUID *object,
2175 const uint8_t *in_data,
2178 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2179 struct rpccli_bh_state);
2180 struct tevent_req *req;
2181 struct rpccli_bh_raw_call_state *state;
2183 struct tevent_req *subreq;
2185 req = tevent_req_create(mem_ctx, &state,
2186 struct rpccli_bh_raw_call_state);
2190 state->in_data.data = discard_const_p(uint8_t, in_data);
2191 state->in_data.length = in_length;
2193 ok = rpccli_bh_is_connected(h);
2195 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2196 return tevent_req_post(req, ev);
2199 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2200 opnum, object, &state->in_data);
2201 if (tevent_req_nomem(subreq, req)) {
2202 return tevent_req_post(req, ev);
2204 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2209 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2211 struct tevent_req *req =
2212 tevent_req_callback_data(subreq,
2214 struct rpccli_bh_raw_call_state *state =
2215 tevent_req_data(req,
2216 struct rpccli_bh_raw_call_state);
2219 state->out_flags = 0;
2221 /* TODO: support bigendian responses */
2223 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2224 TALLOC_FREE(subreq);
2225 if (tevent_req_nterror(req, status)) {
2229 tevent_req_done(req);
2232 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2233 TALLOC_CTX *mem_ctx,
2236 uint32_t *out_flags)
2238 struct rpccli_bh_raw_call_state *state =
2239 tevent_req_data(req,
2240 struct rpccli_bh_raw_call_state);
2243 if (tevent_req_is_nterror(req, &status)) {
2244 tevent_req_received(req);
2248 *out_data = talloc_move(mem_ctx, &state->out_data.data);
2249 *out_length = state->out_data.length;
2250 *out_flags = state->out_flags;
2251 tevent_req_received(req);
2252 return NT_STATUS_OK;
2255 struct rpccli_bh_disconnect_state {
2259 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2260 struct tevent_context *ev,
2261 struct dcerpc_binding_handle *h)
2263 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2264 struct rpccli_bh_state);
2265 struct tevent_req *req;
2266 struct rpccli_bh_disconnect_state *state;
2269 req = tevent_req_create(mem_ctx, &state,
2270 struct rpccli_bh_disconnect_state);
2275 ok = rpccli_bh_is_connected(h);
2277 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2278 return tevent_req_post(req, ev);
2282 * TODO: do a real async disconnect ...
2284 * For now we do it sync...
2286 TALLOC_FREE(hs->rpc_cli->transport);
2289 tevent_req_done(req);
2290 return tevent_req_post(req, ev);
2293 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2295 return tevent_req_simple_recv_ntstatus(req);
2298 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2303 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2305 const void *_struct_ptr,
2306 const struct ndr_interface_call *call)
2308 void *struct_ptr = discard_const(_struct_ptr);
2310 if (DEBUGLEVEL < 10) {
2314 if (ndr_flags & NDR_IN) {
2315 ndr_print_function_debug(call->ndr_print,
2320 if (ndr_flags & NDR_OUT) {
2321 ndr_print_function_debug(call->ndr_print,
2328 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2330 .is_connected = rpccli_bh_is_connected,
2331 .set_timeout = rpccli_bh_set_timeout,
2332 .auth_info = rpccli_bh_auth_info,
2333 .raw_call_send = rpccli_bh_raw_call_send,
2334 .raw_call_recv = rpccli_bh_raw_call_recv,
2335 .disconnect_send = rpccli_bh_disconnect_send,
2336 .disconnect_recv = rpccli_bh_disconnect_recv,
2338 .ref_alloc = rpccli_bh_ref_alloc,
2339 .do_ndr_print = rpccli_bh_do_ndr_print,
2342 /* initialise a rpc_pipe_client binding handle */
2343 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2344 const struct GUID *object,
2345 const struct ndr_interface_table *table)
2347 struct dcerpc_binding_handle *h;
2348 struct rpccli_bh_state *hs;
2350 h = dcerpc_binding_handle_create(c,
2355 struct rpccli_bh_state,
2365 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2366 struct pipe_auth_data **presult)
2368 struct pipe_auth_data *result;
2369 struct auth_generic_state *auth_generic_ctx;
2372 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2373 if (result == NULL) {
2374 return NT_STATUS_NO_MEMORY;
2377 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2378 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2379 result->auth_context_id = 0;
2381 status = auth_generic_client_prepare(result,
2383 if (!NT_STATUS_IS_OK(status)) {
2384 DEBUG(1, ("Failed to create auth_generic context: %s\n",
2385 nt_errstr(status)));
2388 status = auth_generic_set_username(auth_generic_ctx, "");
2389 if (!NT_STATUS_IS_OK(status)) {
2390 DEBUG(1, ("Failed to set username: %s\n",
2391 nt_errstr(status)));
2394 status = auth_generic_set_domain(auth_generic_ctx, "");
2395 if (!NT_STATUS_IS_OK(status)) {
2396 DEBUG(1, ("Failed to set domain: %s\n",
2397 nt_errstr(status)));
2401 status = gensec_set_credentials(auth_generic_ctx->gensec_security,
2402 auth_generic_ctx->credentials);
2403 if (!NT_STATUS_IS_OK(status)) {
2404 DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
2405 nt_errstr(status)));
2408 talloc_unlink(auth_generic_ctx, auth_generic_ctx->credentials);
2409 auth_generic_ctx->credentials = NULL;
2411 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2412 talloc_free(auth_generic_ctx);
2414 return NT_STATUS_OK;
2417 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2418 enum dcerpc_AuthType auth_type,
2419 enum dcerpc_AuthLevel auth_level,
2421 const char *target_service,
2423 const char *username,
2424 const char *password,
2425 enum credentials_use_kerberos use_kerberos,
2426 struct netlogon_creds_CredentialState *creds,
2427 struct pipe_auth_data **presult)
2429 struct auth_generic_state *auth_generic_ctx;
2430 struct pipe_auth_data *result;
2433 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2434 if (result == NULL) {
2435 return NT_STATUS_NO_MEMORY;
2438 result->auth_type = auth_type;
2439 result->auth_level = auth_level;
2440 result->auth_context_id = 1;
2442 status = auth_generic_client_prepare(result,
2444 if (!NT_STATUS_IS_OK(status)) {
2448 status = auth_generic_set_username(auth_generic_ctx, username);
2449 if (!NT_STATUS_IS_OK(status)) {
2453 status = auth_generic_set_domain(auth_generic_ctx, domain);
2454 if (!NT_STATUS_IS_OK(status)) {
2458 status = auth_generic_set_password(auth_generic_ctx, password);
2459 if (!NT_STATUS_IS_OK(status)) {
2463 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2464 if (!NT_STATUS_IS_OK(status)) {
2468 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2469 if (!NT_STATUS_IS_OK(status)) {
2473 cli_credentials_set_kerberos_state(auth_generic_ctx->credentials,
2476 cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
2478 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2479 if (!NT_STATUS_IS_OK(status)) {
2483 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2484 talloc_free(auth_generic_ctx);
2486 return NT_STATUS_OK;
2489 TALLOC_FREE(result);
2493 /* This routine steals the creds pointer that is passed in */
2494 static NTSTATUS rpccli_generic_bind_data_from_creds(TALLOC_CTX *mem_ctx,
2495 enum dcerpc_AuthType auth_type,
2496 enum dcerpc_AuthLevel auth_level,
2498 const char *target_service,
2499 struct cli_credentials *creds,
2500 struct pipe_auth_data **presult)
2502 struct auth_generic_state *auth_generic_ctx;
2503 struct pipe_auth_data *result;
2506 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2507 if (result == NULL) {
2508 return NT_STATUS_NO_MEMORY;
2511 result->auth_type = auth_type;
2512 result->auth_level = auth_level;
2513 result->auth_context_id = 1;
2515 status = auth_generic_client_prepare(result,
2517 if (!NT_STATUS_IS_OK(status)) {
2521 status = auth_generic_set_creds(auth_generic_ctx, creds);
2522 if (!NT_STATUS_IS_OK(status)) {
2526 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2527 if (!NT_STATUS_IS_OK(status)) {
2531 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2532 if (!NT_STATUS_IS_OK(status)) {
2536 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2537 if (!NT_STATUS_IS_OK(status)) {
2541 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2542 talloc_free(auth_generic_ctx);
2544 return NT_STATUS_OK;
2547 TALLOC_FREE(result);
2551 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2552 struct pipe_auth_data **presult)
2554 return rpccli_generic_bind_data(mem_ctx,
2555 DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
2556 DCERPC_AUTH_LEVEL_CONNECT,
2558 "host", /* target_service */
2559 NAME_NT_AUTHORITY, /* domain */
2561 NULL, /* password */
2562 CRED_USE_KERBEROS_DISABLED,
2563 NULL, /* netlogon_creds_CredentialState */
2568 * Create an rpc pipe client struct, connecting to a tcp port.
2570 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2571 const struct sockaddr_storage *ss_addr,
2573 const struct ndr_interface_table *table,
2574 struct rpc_pipe_client **presult)
2576 struct rpc_pipe_client *result;
2577 struct sockaddr_storage addr;
2581 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2582 if (result == NULL) {
2583 return NT_STATUS_NO_MEMORY;
2586 result->abstract_syntax = table->syntax_id;
2587 result->transfer_syntax = ndr_transfer_syntax_ndr;
2589 result->desthost = talloc_strdup(result, host);
2590 if (result->desthost == NULL) {
2591 status = NT_STATUS_NO_MEMORY;
2595 result->srv_name_slash = talloc_asprintf_strupper_m(
2596 result, "\\\\%s", result->desthost);
2597 if (result->srv_name_slash == NULL) {
2598 status = NT_STATUS_NO_MEMORY;
2602 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2604 if (ss_addr == NULL) {
2605 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2606 status = NT_STATUS_NOT_FOUND;
2613 status = open_socket_out(&addr, port, 60*1000, &fd);
2614 if (!NT_STATUS_IS_OK(status)) {
2617 set_socket_options(fd, lp_socket_options());
2619 status = rpc_transport_sock_init(result, fd, &result->transport);
2620 if (!NT_STATUS_IS_OK(status)) {
2625 result->transport->transport = NCACN_IP_TCP;
2627 result->binding_handle = rpccli_bh_create(result, NULL, table);
2628 if (result->binding_handle == NULL) {
2629 TALLOC_FREE(result);
2630 return NT_STATUS_NO_MEMORY;
2634 return NT_STATUS_OK;
2637 TALLOC_FREE(result);
2641 static NTSTATUS rpccli_epm_map_binding(
2642 struct dcerpc_binding_handle *epm_connection,
2643 struct dcerpc_binding *binding,
2644 TALLOC_CTX *mem_ctx,
2647 TALLOC_CTX *frame = talloc_stackframe();
2648 enum dcerpc_transport_t transport =
2649 dcerpc_binding_get_transport(binding);
2650 enum dcerpc_transport_t res_transport;
2651 struct dcerpc_binding *res_binding = NULL;
2652 struct epm_twr_t *map_tower = NULL;
2653 struct epm_twr_p_t res_towers = { .twr = NULL };
2654 struct policy_handle *entry_handle = NULL;
2655 uint32_t num_towers = 0;
2656 const uint32_t max_towers = 1;
2657 const char *endpoint = NULL;
2662 map_tower = talloc_zero(frame, struct epm_twr_t);
2663 if (map_tower == NULL) {
2667 status = dcerpc_binding_build_tower(
2668 frame, binding, &(map_tower->tower));
2669 if (!NT_STATUS_IS_OK(status)) {
2670 DBG_DEBUG("dcerpc_binding_build_tower failed: %s\n",
2675 res_towers.twr = talloc_array(frame, struct epm_twr_t, max_towers);
2676 if (res_towers.twr == NULL) {
2680 entry_handle = talloc_zero(frame, struct policy_handle);
2681 if (entry_handle == NULL) {
2685 status = dcerpc_epm_Map(
2696 if (!NT_STATUS_IS_OK(status)) {
2697 DBG_DEBUG("dcerpc_epm_Map failed: %s\n", nt_errstr(status));
2701 if (result != EPMAPPER_STATUS_OK) {
2702 DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32"\n", result);
2703 status = NT_STATUS_NOT_FOUND;
2707 if (num_towers != 1) {
2708 DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32" towers\n",
2710 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2714 status = dcerpc_binding_from_tower(
2715 frame, &(res_towers.twr->tower), &res_binding);
2716 if (!NT_STATUS_IS_OK(status)) {
2717 DBG_DEBUG("dcerpc_binding_from_tower failed: %s\n",
2722 res_transport = dcerpc_binding_get_transport(res_binding);
2723 if (res_transport != transport) {
2724 DBG_DEBUG("dcerpc_epm_Map returned transport %d, "
2728 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2732 endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
2733 if (endpoint == NULL) {
2734 DBG_DEBUG("dcerpc_epm_Map returned no endpoint\n");
2735 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2739 tmp = talloc_strdup(mem_ctx, endpoint);
2745 status = NT_STATUS_OK;
2749 status = NT_STATUS_NO_MEMORY;
2755 static NTSTATUS rpccli_epm_map_interface(
2756 struct dcerpc_binding_handle *epm_connection,
2757 enum dcerpc_transport_t transport,
2758 const struct ndr_syntax_id *iface,
2759 TALLOC_CTX *mem_ctx,
2762 struct dcerpc_binding *binding = NULL;
2763 char *endpoint = NULL;
2766 status = dcerpc_parse_binding(mem_ctx, "", &binding);
2767 if (!NT_STATUS_IS_OK(status)) {
2768 DBG_DEBUG("dcerpc_parse_binding failed: %s\n",
2773 status = dcerpc_binding_set_transport(binding, transport);
2774 if (!NT_STATUS_IS_OK(status)) {
2775 DBG_DEBUG("dcerpc_binding_set_transport failed: %s\n",
2780 status = dcerpc_binding_set_abstract_syntax(binding, iface);
2781 if (!NT_STATUS_IS_OK(status)) {
2782 DBG_DEBUG("dcerpc_binding_set_abstract_syntax failed: %s\n",
2787 status = rpccli_epm_map_binding(
2788 epm_connection, binding, mem_ctx, &endpoint);
2789 if (!NT_STATUS_IS_OK(status)) {
2790 DBG_DEBUG("rpccli_epm_map_binding failed: %s\n",
2794 *pendpoint = endpoint;
2797 TALLOC_FREE(binding);
2802 * Determine the tcp port on which a dcerpc interface is listening
2803 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2806 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2807 const struct sockaddr_storage *addr,
2808 const struct ndr_interface_table *table,
2812 struct rpc_pipe_client *epm_pipe = NULL;
2813 struct pipe_auth_data *auth = NULL;
2814 char *endpoint = NULL;
2815 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2817 if (pport == NULL) {
2818 status = NT_STATUS_INVALID_PARAMETER;
2822 if (ndr_syntax_id_equal(&table->syntax_id,
2823 &ndr_table_epmapper.syntax_id)) {
2825 status = NT_STATUS_OK;
2829 /* open the connection to the endpoint mapper */
2830 status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2831 &ndr_table_epmapper,
2834 if (!NT_STATUS_IS_OK(status)) {
2838 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2839 if (!NT_STATUS_IS_OK(status)) {
2843 status = rpc_pipe_bind(epm_pipe, auth);
2844 if (!NT_STATUS_IS_OK(status)) {
2848 status = rpccli_epm_map_interface(
2849 epm_pipe->binding_handle,
2854 if (!NT_STATUS_IS_OK(status)) {
2855 DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
2860 *pport = (uint16_t)atoi(endpoint);
2863 TALLOC_FREE(tmp_ctx);
2868 * Create a rpc pipe client struct, connecting to a host via tcp.
2869 * The port is determined by asking the endpoint mapper on the given
2872 static NTSTATUS rpc_pipe_open_tcp(
2873 TALLOC_CTX *mem_ctx,
2875 const struct sockaddr_storage *addr,
2876 const struct ndr_interface_table *table,
2877 struct rpc_pipe_client **presult)
2882 status = rpc_pipe_get_tcp_port(host, addr, table, &port);
2883 if (!NT_STATUS_IS_OK(status)) {
2887 return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2891 static NTSTATUS rpc_pipe_get_ncalrpc_name(
2892 const struct ndr_syntax_id *iface,
2893 TALLOC_CTX *mem_ctx,
2894 char **psocket_name)
2896 TALLOC_CTX *frame = talloc_stackframe();
2897 struct rpc_pipe_client *epm_pipe = NULL;
2898 struct pipe_auth_data *auth = NULL;
2899 NTSTATUS status = NT_STATUS_OK;
2902 is_epm = ndr_syntax_id_equal(iface, &ndr_table_epmapper.syntax_id);
2904 char *endpoint = talloc_strdup(mem_ctx, "EPMAPPER");
2905 if (endpoint == NULL) {
2906 status = NT_STATUS_NO_MEMORY;
2909 *psocket_name = endpoint;
2913 status = rpc_pipe_open_ncalrpc(
2914 frame, &ndr_table_epmapper, &epm_pipe);
2915 if (!NT_STATUS_IS_OK(status)) {
2916 DBG_DEBUG("rpc_pipe_open_ncalrpc failed: %s\n",
2921 status = rpccli_anon_bind_data(epm_pipe, &auth);
2922 if (!NT_STATUS_IS_OK(status)) {
2923 DBG_DEBUG("rpccli_anon_bind_data failed: %s\n",
2928 status = rpc_pipe_bind(epm_pipe, auth);
2929 if (!NT_STATUS_IS_OK(status)) {
2930 DBG_DEBUG("rpc_pipe_bind failed: %s\n", nt_errstr(status));
2934 status = rpccli_epm_map_interface(
2935 epm_pipe->binding_handle,
2940 if (!NT_STATUS_IS_OK(status)) {
2941 DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
2950 /********************************************************************
2951 Create a rpc pipe client struct, connecting to a unix domain socket
2952 ********************************************************************/
2953 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx,
2954 const struct ndr_interface_table *table,
2955 struct rpc_pipe_client **presult)
2957 char *socket_name = NULL;
2958 struct rpc_pipe_client *result;
2959 struct sockaddr_un addr = { .sun_family = AF_UNIX };
2960 socklen_t salen = sizeof(addr);
2965 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2966 if (result == NULL) {
2967 return NT_STATUS_NO_MEMORY;
2970 status = rpc_pipe_get_ncalrpc_name(
2971 &table->syntax_id, result, &socket_name);
2972 if (!NT_STATUS_IS_OK(status)) {
2973 DBG_DEBUG("rpc_pipe_get_ncalrpc_name failed: %s\n",
2980 sizeof(addr.sun_path),
2984 if ((pathlen < 0) || ((size_t)pathlen >= sizeof(addr.sun_path))) {
2985 DBG_DEBUG("socket_path for %s too long\n", socket_name);
2986 status = NT_STATUS_NAME_TOO_LONG;
2989 TALLOC_FREE(socket_name);
2991 result->abstract_syntax = table->syntax_id;
2992 result->transfer_syntax = ndr_transfer_syntax_ndr;
2994 result->desthost = get_myname(result);
2995 if (result->desthost == NULL) {
2996 status = NT_STATUS_NO_MEMORY;
3000 result->srv_name_slash = talloc_asprintf_strupper_m(
3001 result, "\\\\%s", result->desthost);
3002 if (result->srv_name_slash == NULL) {
3003 status = NT_STATUS_NO_MEMORY;
3007 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3009 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3011 status = map_nt_error_from_unix(errno);
3015 if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
3016 DBG_ERR("connect(%s) failed: %s\n",
3019 status = map_nt_error_from_unix(errno);
3023 status = rpc_transport_sock_init(result, fd, &result->transport);
3024 if (!NT_STATUS_IS_OK(status)) {
3029 result->transport->transport = NCALRPC;
3031 result->binding_handle = rpccli_bh_create(result, NULL, table);
3032 if (result->binding_handle == NULL) {
3033 status = NT_STATUS_NO_MEMORY;
3038 return NT_STATUS_OK;
3044 TALLOC_FREE(result);
3048 struct rpc_pipe_client_np_ref {
3049 struct cli_state *cli;
3050 struct rpc_pipe_client *pipe;
3053 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3055 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3059 /****************************************************************************
3060 Open a named pipe over SMB to a remote server.
3062 * CAVEAT CALLER OF THIS FUNCTION:
3063 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3064 * so be sure that this function is called AFTER any structure (vs pointer)
3065 * assignment of the cli. In particular, libsmbclient does structure
3066 * assignments of cli, which invalidates the data in the returned
3067 * rpc_pipe_client if this function is called before the structure assignment
3070 ****************************************************************************/
3072 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3073 const struct ndr_interface_table *table,
3074 struct rpc_pipe_client **presult)
3076 struct rpc_pipe_client *result;
3078 struct rpc_pipe_client_np_ref *np_ref;
3080 /* sanity check to protect against crashes */
3083 return NT_STATUS_INVALID_HANDLE;
3086 result = talloc_zero(NULL, struct rpc_pipe_client);
3087 if (result == NULL) {
3088 return NT_STATUS_NO_MEMORY;
3091 result->abstract_syntax = table->syntax_id;
3092 result->transfer_syntax = ndr_transfer_syntax_ndr;
3094 result->desthost = talloc_strdup(
3095 result, smbXcli_conn_remote_name(cli->conn));
3096 if (result->desthost == NULL) {
3097 TALLOC_FREE(result);
3098 return NT_STATUS_NO_MEMORY;
3101 result->srv_name_slash = talloc_asprintf_strupper_m(
3102 result, "\\\\%s", result->desthost);
3103 if (result->srv_name_slash == NULL) {
3104 TALLOC_FREE(result);
3105 return NT_STATUS_NO_MEMORY;
3108 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3110 status = rpc_transport_np_init(result, cli, table,
3111 &result->transport);
3112 if (!NT_STATUS_IS_OK(status)) {
3113 TALLOC_FREE(result);
3117 result->transport->transport = NCACN_NP;
3119 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3120 if (np_ref == NULL) {
3121 TALLOC_FREE(result);
3122 return NT_STATUS_NO_MEMORY;
3125 np_ref->pipe = result;
3127 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3128 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3130 result->binding_handle = rpccli_bh_create(result, NULL, table);
3131 if (result->binding_handle == NULL) {
3132 TALLOC_FREE(result);
3133 return NT_STATUS_NO_MEMORY;
3137 return NT_STATUS_OK;
3140 /****************************************************************************
3141 Open a pipe to a remote server.
3142 ****************************************************************************/
3144 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3145 enum dcerpc_transport_t transport,
3146 const struct ndr_interface_table *table,
3147 struct rpc_pipe_client **presult)
3149 switch (transport) {
3151 return rpc_pipe_open_tcp(NULL,
3152 smbXcli_conn_remote_name(cli->conn),
3153 smbXcli_conn_remote_sockaddr(cli->conn),
3156 return rpc_pipe_open_np(cli, table, presult);
3158 return NT_STATUS_NOT_IMPLEMENTED;
3162 /****************************************************************************
3163 Open a named pipe to an SMB server and bind anonymously.
3164 ****************************************************************************/
3166 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3167 enum dcerpc_transport_t transport,
3168 const struct ndr_interface_table *table,
3169 struct rpc_pipe_client **presult)
3171 struct rpc_pipe_client *result;
3172 struct pipe_auth_data *auth;
3175 status = cli_rpc_pipe_open(cli, transport, table, &result);
3176 if (!NT_STATUS_IS_OK(status)) {
3180 status = rpccli_anon_bind_data(result, &auth);
3181 if (!NT_STATUS_IS_OK(status)) {
3182 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3183 nt_errstr(status)));
3184 TALLOC_FREE(result);
3189 * This is a bit of an abstraction violation due to the fact that an
3190 * anonymous bind on an authenticated SMB inherits the user/domain
3191 * from the enclosing SMB creds
3194 if (transport == NCACN_NP) {
3195 struct smbXcli_session *session;
3197 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3198 session = cli->smb2.session;
3200 session = cli->smb1.session;
3203 status = smbXcli_session_application_key(session, auth,
3204 &auth->transport_session_key);
3205 if (!NT_STATUS_IS_OK(status)) {
3206 auth->transport_session_key = data_blob_null;
3210 status = rpc_pipe_bind(result, auth);
3211 if (!NT_STATUS_IS_OK(status)) {
3213 if (ndr_syntax_id_equal(&table->syntax_id,
3214 &ndr_table_dssetup.syntax_id)) {
3215 /* non AD domains just don't have this pipe, avoid
3216 * level 0 statement in that case - gd */
3219 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3220 "%s failed with error %s\n",
3222 nt_errstr(status) ));
3223 TALLOC_FREE(result);
3227 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3228 "%s and bound anonymously.\n",
3233 return NT_STATUS_OK;
3236 /****************************************************************************
3237 ****************************************************************************/
3239 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3240 const struct ndr_interface_table *table,
3241 struct rpc_pipe_client **presult)
3243 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3247 /****************************************************************************
3248 Open a named pipe to an SMB server and bind using the mech specified
3250 This routine references the creds pointer that is passed in
3251 ****************************************************************************/
3253 NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
3254 const struct ndr_interface_table *table,
3255 enum dcerpc_transport_t transport,
3256 enum dcerpc_AuthType auth_type,
3257 enum dcerpc_AuthLevel auth_level,
3259 struct cli_credentials *creds,
3260 struct rpc_pipe_client **presult)
3262 struct rpc_pipe_client *result;
3263 struct pipe_auth_data *auth = NULL;
3264 const char *target_service = table->authservices->names[0];
3267 status = cli_rpc_pipe_open(cli, transport, table, &result);
3268 if (!NT_STATUS_IS_OK(status)) {
3272 status = rpccli_generic_bind_data_from_creds(result,
3273 auth_type, auth_level,
3274 server, target_service,
3277 if (!NT_STATUS_IS_OK(status)) {
3278 DBG_ERR("rpccli_generic_bind_data_from_creds returned %s\n",
3283 status = rpc_pipe_bind(result, auth);
3284 if (!NT_STATUS_IS_OK(status)) {
3285 DBG_ERR("cli_rpc_pipe_bind failed with error %s\n",
3290 DBG_DEBUG("opened pipe %s to machine %s and bound as user %s.\n",
3293 cli_credentials_get_unparsed_name(creds, talloc_tos()));
3296 return NT_STATUS_OK;
3300 TALLOC_FREE(result);
3304 NTSTATUS cli_rpc_pipe_open_bind_schannel(
3305 struct cli_state *cli,
3306 const struct ndr_interface_table *table,
3307 enum dcerpc_transport_t transport,
3308 struct netlogon_creds_cli_context *netlogon_creds,
3309 struct rpc_pipe_client **_rpccli)
3311 struct rpc_pipe_client *rpccli;
3312 struct pipe_auth_data *rpcauth;
3313 const char *target_service = table->authservices->names[0];
3314 struct cli_credentials *cli_creds;
3315 enum dcerpc_AuthLevel auth_level;
3318 status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
3319 if (!NT_STATUS_IS_OK(status)) {
3323 auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
3325 status = netlogon_creds_bind_cli_credentials(
3326 netlogon_creds, rpccli, &cli_creds);
3327 if (!NT_STATUS_IS_OK(status)) {
3328 DBG_DEBUG("netlogon_creds_bind_cli_credentials failed: %s\n",
3330 TALLOC_FREE(rpccli);
3334 status = rpccli_generic_bind_data_from_creds(rpccli,
3335 DCERPC_AUTH_TYPE_SCHANNEL,
3341 if (!NT_STATUS_IS_OK(status)) {
3342 DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
3343 nt_errstr(status)));
3344 TALLOC_FREE(rpccli);
3348 status = rpc_pipe_bind(rpccli, rpcauth);
3350 /* No TALLOC_FREE, gensec takes references */
3351 talloc_unlink(rpccli, cli_creds);
3354 if (!NT_STATUS_IS_OK(status)) {
3355 DBG_DEBUG("rpc_pipe_bind failed with error %s\n",
3357 TALLOC_FREE(rpccli);
3363 return NT_STATUS_OK;
3366 NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
3367 const struct ndr_interface_table *table,
3368 enum dcerpc_transport_t transport,
3369 struct netlogon_creds_cli_context *netlogon_creds,
3370 struct rpc_pipe_client **_rpccli)
3372 TALLOC_CTX *frame = talloc_stackframe();
3373 struct rpc_pipe_client *rpccli;
3374 struct netlogon_creds_cli_lck *lck;
3377 status = netlogon_creds_cli_lck(
3378 netlogon_creds, NETLOGON_CREDS_CLI_LCK_EXCLUSIVE,
3380 if (!NT_STATUS_IS_OK(status)) {
3381 DBG_WARNING("netlogon_creds_cli_lck returned %s\n",
3387 status = cli_rpc_pipe_open_bind_schannel(
3388 cli, table, transport, netlogon_creds, &rpccli);
3389 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3390 netlogon_creds_cli_delete_lck(netlogon_creds);
3392 if (!NT_STATUS_IS_OK(status)) {
3393 DBG_DEBUG("cli_rpc_pipe_open_bind_schannel failed: %s\n",
3399 if (ndr_syntax_id_equal(&table->syntax_id,
3400 &ndr_table_netlogon.syntax_id)) {
3401 status = netlogon_creds_cli_check(netlogon_creds,
3402 rpccli->binding_handle,
3404 if (!NT_STATUS_IS_OK(status)) {
3405 DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
3406 nt_errstr(status)));
3412 DBG_DEBUG("opened pipe %s to machine %s with key %s "
3413 "and bound using schannel.\n",
3414 table->name, rpccli->desthost,
3415 netlogon_creds_cli_debug_string(netlogon_creds, lck));
3420 return NT_STATUS_OK;
3423 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3424 struct rpc_pipe_client *cli,
3425 DATA_BLOB *session_key)
3428 struct pipe_auth_data *a;
3429 struct gensec_security *gensec_security;
3430 DATA_BLOB sk = { .data = NULL };
3431 bool make_dup = false;
3433 if (!session_key || !cli) {
3434 return NT_STATUS_INVALID_PARAMETER;
3440 return NT_STATUS_INVALID_PARAMETER;
3443 switch (cli->auth->auth_type) {
3444 case DCERPC_AUTH_TYPE_NONE:
3445 sk = data_blob_const(a->transport_session_key.data,
3446 a->transport_session_key.length);
3450 gensec_security = a->auth_ctx;
3451 status = gensec_session_key(gensec_security, mem_ctx, &sk);
3452 if (!NT_STATUS_IS_OK(status)) {
3460 return NT_STATUS_NO_USER_SESSION_KEY;
3464 *session_key = data_blob_dup_talloc(mem_ctx, sk);
3469 return NT_STATUS_OK;