2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client routines
4 * Largely rewritten by Jeremy Allison 2005.
5 * Heavily modified by Simo Sorce 2010.
6 * Copyright Andrew Bartlett 2011.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "../lib/util/tevent_ntstatus.h"
24 #include "librpc/gen_ndr/ndr_epmapper_c.h"
25 #include "../librpc/gen_ndr/ndr_dssetup.h"
26 #include "../libcli/auth/schannel.h"
27 #include "../libcli/auth/netlogon_creds_cli.h"
28 #include "auth_generic.h"
29 #include "librpc/gen_ndr/ndr_dcerpc.h"
30 #include "librpc/gen_ndr/ndr_netlogon_c.h"
31 #include "librpc/rpc/dcerpc.h"
34 #include "libsmb/libsmb.h"
35 #include "auth/gensec/gensec.h"
36 #include "auth/credentials/credentials.h"
37 #include "../libcli/smb/smbXcli_base.h"
40 #define DBGC_CLASS DBGC_RPC_CLI
42 /********************************************************************
43 Pipe description for a DEBUG
44 ********************************************************************/
45 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
46 struct rpc_pipe_client *cli)
48 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
55 /********************************************************************
57 ********************************************************************/
59 static uint32_t get_rpc_call_id(void)
61 static uint32_t call_id = 0;
65 /*******************************************************************
66 Use SMBreadX to get rest of one fragment's worth of rpc data.
67 Reads the whole size or give an error message
68 ********************************************************************/
70 struct rpc_read_state {
71 struct tevent_context *ev;
72 struct rpc_cli_transport *transport;
78 static void rpc_read_done(struct tevent_req *subreq);
80 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
81 struct tevent_context *ev,
82 struct rpc_cli_transport *transport,
83 uint8_t *data, size_t size)
85 struct tevent_req *req, *subreq;
86 struct rpc_read_state *state;
88 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
93 state->transport = transport;
98 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
100 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
102 if (subreq == NULL) {
105 tevent_req_set_callback(subreq, rpc_read_done, req);
113 static void rpc_read_done(struct tevent_req *subreq)
115 struct tevent_req *req = tevent_req_callback_data(
116 subreq, struct tevent_req);
117 struct rpc_read_state *state = tevent_req_data(
118 req, struct rpc_read_state);
122 status = state->transport->read_recv(subreq, &received);
124 if (!NT_STATUS_IS_OK(status)) {
125 tevent_req_nterror(req, status);
129 state->num_read += received;
130 if (state->num_read == state->size) {
131 tevent_req_done(req);
135 subreq = state->transport->read_send(state, state->ev,
136 state->data + state->num_read,
137 state->size - state->num_read,
138 state->transport->priv);
139 if (tevent_req_nomem(subreq, req)) {
142 tevent_req_set_callback(subreq, rpc_read_done, req);
145 static NTSTATUS rpc_read_recv(struct tevent_req *req)
147 return tevent_req_simple_recv_ntstatus(req);
150 struct rpc_write_state {
151 struct tevent_context *ev;
152 struct rpc_cli_transport *transport;
158 static void rpc_write_done(struct tevent_req *subreq);
160 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
161 struct tevent_context *ev,
162 struct rpc_cli_transport *transport,
163 const uint8_t *data, size_t size)
165 struct tevent_req *req, *subreq;
166 struct rpc_write_state *state;
168 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
173 state->transport = transport;
176 state->num_written = 0;
178 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
180 subreq = transport->write_send(state, ev, data, size, transport->priv);
181 if (subreq == NULL) {
184 tevent_req_set_callback(subreq, rpc_write_done, req);
191 static void rpc_write_done(struct tevent_req *subreq)
193 struct tevent_req *req = tevent_req_callback_data(
194 subreq, struct tevent_req);
195 struct rpc_write_state *state = tevent_req_data(
196 req, struct rpc_write_state);
200 status = state->transport->write_recv(subreq, &written);
202 if (!NT_STATUS_IS_OK(status)) {
203 tevent_req_nterror(req, status);
207 state->num_written += written;
209 if (state->num_written == state->size) {
210 tevent_req_done(req);
214 subreq = state->transport->write_send(state, state->ev,
215 state->data + state->num_written,
216 state->size - state->num_written,
217 state->transport->priv);
218 if (tevent_req_nomem(subreq, req)) {
221 tevent_req_set_callback(subreq, rpc_write_done, req);
224 static NTSTATUS rpc_write_recv(struct tevent_req *req)
226 return tevent_req_simple_recv_ntstatus(req);
230 /****************************************************************************
231 Try and get a PDU's worth of data from current_pdu. If not, then read more
233 ****************************************************************************/
235 struct get_complete_frag_state {
236 struct tevent_context *ev;
237 struct rpc_pipe_client *cli;
242 static void get_complete_frag_got_header(struct tevent_req *subreq);
243 static void get_complete_frag_got_rest(struct tevent_req *subreq);
245 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
246 struct tevent_context *ev,
247 struct rpc_pipe_client *cli,
250 struct tevent_req *req, *subreq;
251 struct get_complete_frag_state *state;
255 req = tevent_req_create(mem_ctx, &state,
256 struct get_complete_frag_state);
262 state->frag_len = RPC_HEADER_LEN;
265 received = pdu->length;
266 if (received < RPC_HEADER_LEN) {
267 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
268 status = NT_STATUS_NO_MEMORY;
271 subreq = rpc_read_send(state, state->ev,
272 state->cli->transport,
273 pdu->data + received,
274 RPC_HEADER_LEN - received);
275 if (subreq == NULL) {
276 status = NT_STATUS_NO_MEMORY;
279 tevent_req_set_callback(subreq, get_complete_frag_got_header,
284 state->frag_len = dcerpc_get_frag_length(pdu);
285 if (state->frag_len < RPC_HEADER_LEN) {
286 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
287 return tevent_req_post(req, ev);
291 * Ensure we have frag_len bytes of data.
293 if (received < state->frag_len) {
294 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
295 status = NT_STATUS_NO_MEMORY;
298 subreq = rpc_read_send(state, state->ev,
299 state->cli->transport,
300 pdu->data + received,
301 state->frag_len - received);
302 if (subreq == NULL) {
303 status = NT_STATUS_NO_MEMORY;
306 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
311 status = NT_STATUS_OK;
313 if (NT_STATUS_IS_OK(status)) {
314 tevent_req_done(req);
316 tevent_req_nterror(req, status);
318 return tevent_req_post(req, ev);
321 static void get_complete_frag_got_header(struct tevent_req *subreq)
323 struct tevent_req *req = tevent_req_callback_data(
324 subreq, struct tevent_req);
325 struct get_complete_frag_state *state = tevent_req_data(
326 req, struct get_complete_frag_state);
329 status = rpc_read_recv(subreq);
331 if (!NT_STATUS_IS_OK(status)) {
332 tevent_req_nterror(req, status);
336 state->frag_len = dcerpc_get_frag_length(state->pdu);
337 if (state->frag_len < RPC_HEADER_LEN) {
338 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
342 if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
343 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
348 * We're here in this piece of code because we've read exactly
349 * RPC_HEADER_LEN bytes into state->pdu.
352 subreq = rpc_read_send(state, state->ev, state->cli->transport,
353 state->pdu->data + RPC_HEADER_LEN,
354 state->frag_len - RPC_HEADER_LEN);
355 if (tevent_req_nomem(subreq, req)) {
358 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
361 static void get_complete_frag_got_rest(struct tevent_req *subreq)
363 struct tevent_req *req = tevent_req_callback_data(
364 subreq, struct tevent_req);
367 status = rpc_read_recv(subreq);
369 if (!NT_STATUS_IS_OK(status)) {
370 tevent_req_nterror(req, status);
373 tevent_req_done(req);
376 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
378 return tevent_req_simple_recv_ntstatus(req);
381 /****************************************************************************
382 Do basic authentication checks on an incoming pdu.
383 ****************************************************************************/
385 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
386 struct rpc_pipe_client *cli,
387 struct ncacn_packet *pkt,
389 uint8_t expected_pkt_type,
392 DATA_BLOB *reply_pdu)
394 const struct dcerpc_response *r = NULL;
395 DATA_BLOB tmp_stub = data_blob_null;
396 NTSTATUS ret = NT_STATUS_OK;
399 * Point the return values at the real data including the RPC
400 * header. Just in case the caller wants it.
404 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
405 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
407 * TODO: do we still need this hack which was introduced
408 * in commit a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0.
410 * I don't even know what AS/U might be...
412 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
413 "fragment first/last ON.\n"));
414 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
417 /* Ensure we have the correct type. */
418 switch (pkt->ptype) {
419 case DCERPC_PKT_BIND_NAK:
420 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
421 rpccli_pipe_txt(talloc_tos(), cli)));
423 ret = dcerpc_verify_ncacn_packet_header(pkt,
425 0, /* max_auth_info */
426 DCERPC_PFC_FLAG_FIRST |
427 DCERPC_PFC_FLAG_LAST,
428 0); /* optional flags */
429 if (!NT_STATUS_IS_OK(ret)) {
430 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
431 "RPC packet type - %u, expected %u: %s\n",
432 rpccli_pipe_txt(talloc_tos(), cli),
433 pkt->ptype, expected_pkt_type,
435 NDR_PRINT_DEBUG(ncacn_packet, pkt);
439 /* Use this for now... */
440 return NT_STATUS_NETWORK_ACCESS_DENIED;
442 case DCERPC_PKT_BIND_ACK:
443 ret = dcerpc_verify_ncacn_packet_header(pkt,
445 pkt->u.bind_ack.auth_info.length,
446 DCERPC_PFC_FLAG_FIRST |
447 DCERPC_PFC_FLAG_LAST,
448 DCERPC_PFC_FLAG_CONC_MPX |
449 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
450 if (!NT_STATUS_IS_OK(ret)) {
451 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
452 "RPC packet type - %u, expected %u: %s\n",
453 rpccli_pipe_txt(talloc_tos(), cli),
454 pkt->ptype, expected_pkt_type,
456 NDR_PRINT_DEBUG(ncacn_packet, pkt);
462 case DCERPC_PKT_ALTER_RESP:
463 ret = dcerpc_verify_ncacn_packet_header(pkt,
465 pkt->u.alter_resp.auth_info.length,
466 DCERPC_PFC_FLAG_FIRST |
467 DCERPC_PFC_FLAG_LAST,
468 DCERPC_PFC_FLAG_CONC_MPX |
469 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
470 if (!NT_STATUS_IS_OK(ret)) {
471 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
472 "RPC packet type - %u, expected %u: %s\n",
473 rpccli_pipe_txt(talloc_tos(), cli),
474 pkt->ptype, expected_pkt_type,
476 NDR_PRINT_DEBUG(ncacn_packet, pkt);
482 case DCERPC_PKT_RESPONSE:
484 r = &pkt->u.response;
486 ret = dcerpc_verify_ncacn_packet_header(pkt,
488 r->stub_and_verifier.length,
489 0, /* required_flags */
490 DCERPC_PFC_FLAG_FIRST |
491 DCERPC_PFC_FLAG_LAST);
492 if (!NT_STATUS_IS_OK(ret)) {
493 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
494 "RPC packet type - %u, expected %u: %s\n",
495 rpccli_pipe_txt(talloc_tos(), cli),
496 pkt->ptype, expected_pkt_type,
498 NDR_PRINT_DEBUG(ncacn_packet, pkt);
502 tmp_stub.data = r->stub_and_verifier.data;
503 tmp_stub.length = r->stub_and_verifier.length;
505 /* Here's where we deal with incoming sign/seal. */
506 ret = dcerpc_check_auth(cli->auth, pkt,
508 DCERPC_RESPONSE_LENGTH,
510 if (!NT_STATUS_IS_OK(ret)) {
511 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
512 "RPC packet type - %u, expected %u: %s\n",
513 rpccli_pipe_txt(talloc_tos(), cli),
514 pkt->ptype, expected_pkt_type,
516 NDR_PRINT_DEBUG(ncacn_packet, pkt);
520 /* Point the return values at the NDR data. */
523 DEBUG(10, ("Got pdu len %lu, data_len %lu\n",
524 (long unsigned int)pdu->length,
525 (long unsigned int)rdata->length));
528 * If this is the first reply, and the allocation hint is
529 * reasonable, try and set up the reply_pdu DATA_BLOB to the
533 if ((reply_pdu->length == 0) &&
534 r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
535 if (!data_blob_realloc(mem_ctx, reply_pdu,
537 DEBUG(0, ("reply alloc hint %d too "
538 "large to allocate\n",
539 (int)r->alloc_hint));
540 return NT_STATUS_NO_MEMORY;
546 case DCERPC_PKT_FAULT:
548 ret = dcerpc_verify_ncacn_packet_header(pkt,
550 0, /* max_auth_info */
551 DCERPC_PFC_FLAG_FIRST |
552 DCERPC_PFC_FLAG_LAST,
553 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
554 if (!NT_STATUS_IS_OK(ret)) {
555 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
556 "RPC packet type - %u, expected %u: %s\n",
557 rpccli_pipe_txt(talloc_tos(), cli),
558 pkt->ptype, expected_pkt_type,
560 NDR_PRINT_DEBUG(ncacn_packet, pkt);
564 DEBUG(1, (__location__ ": RPC fault code %s received "
566 dcerpc_errstr(talloc_tos(),
567 pkt->u.fault.status),
568 rpccli_pipe_txt(talloc_tos(), cli)));
570 return dcerpc_fault_to_nt_status(pkt->u.fault.status);
573 DEBUG(0, (__location__ "Unknown packet type %u received "
575 (unsigned int)pkt->ptype,
576 rpccli_pipe_txt(talloc_tos(), cli)));
577 return NT_STATUS_RPC_PROTOCOL_ERROR;
581 if (pkt->call_id != call_id) {
582 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
583 "RPC call_id - %u, not %u\n",
584 rpccli_pipe_txt(talloc_tos(), cli),
585 pkt->call_id, call_id));
586 return NT_STATUS_RPC_PROTOCOL_ERROR;
592 /****************************************************************************
593 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
594 ****************************************************************************/
596 struct cli_api_pipe_state {
597 struct tevent_context *ev;
598 struct rpc_cli_transport *transport;
603 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
604 static void cli_api_pipe_write_done(struct tevent_req *subreq);
605 static void cli_api_pipe_read_done(struct tevent_req *subreq);
607 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
608 struct tevent_context *ev,
609 struct rpc_cli_transport *transport,
610 uint8_t *data, size_t data_len,
611 uint32_t max_rdata_len)
613 struct tevent_req *req, *subreq;
614 struct cli_api_pipe_state *state;
617 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
622 state->transport = transport;
624 if (max_rdata_len < RPC_HEADER_LEN) {
626 * For a RPC reply we always need at least RPC_HEADER_LEN
627 * bytes. We check this here because we will receive
628 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
630 status = NT_STATUS_INVALID_PARAMETER;
634 if (transport->trans_send != NULL) {
635 subreq = transport->trans_send(state, ev, data, data_len,
636 max_rdata_len, transport->priv);
637 if (subreq == NULL) {
640 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
645 * If the transport does not provide a "trans" routine, i.e. for
646 * example the ncacn_ip_tcp transport, do the write/read step here.
649 subreq = rpc_write_send(state, ev, transport, data, data_len);
650 if (subreq == NULL) {
653 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
657 tevent_req_nterror(req, status);
658 return tevent_req_post(req, ev);
664 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
666 struct tevent_req *req = tevent_req_callback_data(
667 subreq, struct tevent_req);
668 struct cli_api_pipe_state *state = tevent_req_data(
669 req, struct cli_api_pipe_state);
672 status = state->transport->trans_recv(subreq, state, &state->rdata,
675 if (!NT_STATUS_IS_OK(status)) {
676 tevent_req_nterror(req, status);
679 tevent_req_done(req);
682 static void cli_api_pipe_write_done(struct tevent_req *subreq)
684 struct tevent_req *req = tevent_req_callback_data(
685 subreq, struct tevent_req);
686 struct cli_api_pipe_state *state = tevent_req_data(
687 req, struct cli_api_pipe_state);
690 status = rpc_write_recv(subreq);
692 if (!NT_STATUS_IS_OK(status)) {
693 tevent_req_nterror(req, status);
697 state->rdata = talloc_array(state, uint8_t, RPC_HEADER_LEN);
698 if (tevent_req_nomem(state->rdata, req)) {
703 * We don't need to use rpc_read_send here, the upper layer will cope
704 * with a short read, transport->trans_send could also return less
705 * than state->max_rdata_len.
707 subreq = state->transport->read_send(state, state->ev, state->rdata,
709 state->transport->priv);
710 if (tevent_req_nomem(subreq, req)) {
713 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
716 static void cli_api_pipe_read_done(struct tevent_req *subreq)
718 struct tevent_req *req = tevent_req_callback_data(
719 subreq, struct tevent_req);
720 struct cli_api_pipe_state *state = tevent_req_data(
721 req, struct cli_api_pipe_state);
725 status = state->transport->read_recv(subreq, &received);
727 if (!NT_STATUS_IS_OK(status)) {
728 tevent_req_nterror(req, status);
731 state->rdata_len = received;
732 tevent_req_done(req);
735 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
736 uint8_t **prdata, uint32_t *prdata_len)
738 struct cli_api_pipe_state *state = tevent_req_data(
739 req, struct cli_api_pipe_state);
742 if (tevent_req_is_nterror(req, &status)) {
746 *prdata = talloc_move(mem_ctx, &state->rdata);
747 *prdata_len = state->rdata_len;
751 /****************************************************************************
752 Send data on an rpc pipe via trans. The data must be the last
753 pdu fragment of an NDR data stream.
755 Receive response data from an rpc pipe, which may be large...
757 Read the first fragment: unfortunately have to use SMBtrans for the first
758 bit, then SMBreadX for subsequent bits.
760 If first fragment received also wasn't the last fragment, continue
761 getting fragments until we _do_ receive the last fragment.
763 Request/Response PDU's look like the following...
765 |<------------------PDU len----------------------------------------------->|
766 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
768 +------------+-----------------+-------------+---------------+-------------+
769 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
770 +------------+-----------------+-------------+---------------+-------------+
772 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
773 signing & sealing being negotiated.
775 ****************************************************************************/
777 struct rpc_api_pipe_state {
778 struct tevent_context *ev;
779 struct rpc_pipe_client *cli;
780 uint8_t expected_pkt_type;
783 DATA_BLOB incoming_frag;
784 struct ncacn_packet *pkt;
788 size_t reply_pdu_offset;
792 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
793 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
794 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq);
796 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
797 struct tevent_context *ev,
798 struct rpc_pipe_client *cli,
799 DATA_BLOB *data, /* Outgoing PDU */
800 uint8_t expected_pkt_type,
803 struct tevent_req *req, *subreq;
804 struct rpc_api_pipe_state *state;
805 uint16_t max_recv_frag;
808 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
814 state->expected_pkt_type = expected_pkt_type;
815 state->call_id = call_id;
816 state->endianess = DCERPC_DREP_LE;
819 * Ensure we're not sending too much.
821 if (data->length > cli->max_xmit_frag) {
822 status = NT_STATUS_INVALID_PARAMETER;
826 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
828 if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
829 subreq = rpc_write_send(state, ev, cli->transport,
830 data->data, data->length);
831 if (subreq == NULL) {
834 tevent_req_set_callback(subreq, rpc_api_pipe_auth3_done, req);
838 /* get the header first, then fetch the rest once we have
839 * the frag_length available */
840 max_recv_frag = RPC_HEADER_LEN;
842 subreq = cli_api_pipe_send(state, ev, cli->transport,
843 data->data, data->length, max_recv_frag);
844 if (subreq == NULL) {
847 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
851 tevent_req_nterror(req, status);
852 return tevent_req_post(req, ev);
858 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq)
860 struct tevent_req *req =
861 tevent_req_callback_data(subreq,
865 status = rpc_write_recv(subreq);
867 if (!NT_STATUS_IS_OK(status)) {
868 tevent_req_nterror(req, status);
872 tevent_req_done(req);
875 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
877 struct tevent_req *req = tevent_req_callback_data(
878 subreq, struct tevent_req);
879 struct rpc_api_pipe_state *state = tevent_req_data(
880 req, struct rpc_api_pipe_state);
882 uint8_t *rdata = NULL;
883 uint32_t rdata_len = 0;
885 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
887 if (!NT_STATUS_IS_OK(status)) {
888 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
889 tevent_req_nterror(req, status);
894 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
895 rpccli_pipe_txt(talloc_tos(), state->cli)));
896 tevent_req_done(req);
901 * Move data on state->incoming_frag.
903 state->incoming_frag.data = talloc_move(state, &rdata);
904 state->incoming_frag.length = rdata_len;
905 if (!state->incoming_frag.data) {
906 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
910 /* Ensure we have enough data for a pdu. */
911 subreq = get_complete_frag_send(state, state->ev, state->cli,
912 &state->incoming_frag);
913 if (tevent_req_nomem(subreq, req)) {
916 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
919 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
921 struct tevent_req *req = tevent_req_callback_data(
922 subreq, struct tevent_req);
923 struct rpc_api_pipe_state *state = tevent_req_data(
924 req, struct rpc_api_pipe_state);
926 DATA_BLOB rdata = data_blob_null;
928 status = get_complete_frag_recv(subreq);
930 if (!NT_STATUS_IS_OK(status)) {
931 DEBUG(5, ("get_complete_frag failed: %s\n",
933 tevent_req_nterror(req, status);
937 state->pkt = talloc(state, struct ncacn_packet);
940 * TODO: do a real async disconnect ...
942 * For now do it sync...
944 TALLOC_FREE(state->cli->transport);
945 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
949 status = dcerpc_pull_ncacn_packet(state->pkt,
950 &state->incoming_frag,
952 if (!NT_STATUS_IS_OK(status)) {
954 * TODO: do a real async disconnect ...
956 * For now do it sync...
958 TALLOC_FREE(state->cli->transport);
959 tevent_req_nterror(req, status);
963 if (DEBUGLEVEL >= 10) {
964 NDR_PRINT_DEBUG(ncacn_packet, state->pkt);
967 status = cli_pipe_validate_current_pdu(state,
968 state->cli, state->pkt,
969 &state->incoming_frag,
970 state->expected_pkt_type,
975 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
976 (unsigned)state->incoming_frag.length,
977 (unsigned)state->reply_pdu_offset,
980 if (state->pkt->ptype != DCERPC_PKT_FAULT && !NT_STATUS_IS_OK(status)) {
982 * TODO: do a real async disconnect ...
984 * For now do it sync...
986 TALLOC_FREE(state->cli->transport);
987 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
989 * TODO: do a real async disconnect ...
991 * For now do it sync...
993 TALLOC_FREE(state->cli->transport);
994 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
996 * TODO: do a real async disconnect ...
998 * For now do it sync...
1000 TALLOC_FREE(state->cli->transport);
1002 if (!NT_STATUS_IS_OK(status)) {
1003 tevent_req_nterror(req, status);
1007 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
1008 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
1010 * Set the data type correctly for big-endian data on the
1013 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1015 rpccli_pipe_txt(talloc_tos(), state->cli)));
1016 state->endianess = 0x00; /* BIG ENDIAN */
1019 * Check endianness on subsequent packets.
1021 if (state->endianess != state->pkt->drep[0]) {
1022 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1024 state->endianess?"little":"big",
1025 state->pkt->drep[0]?"little":"big"));
1027 * TODO: do a real async disconnect ...
1029 * For now do it sync...
1031 TALLOC_FREE(state->cli->transport);
1032 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1036 if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) {
1038 * TODO: do a real async disconnect ...
1040 * For now do it sync...
1042 TALLOC_FREE(state->cli->transport);
1043 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1047 /* Now copy the data portion out of the pdu into rbuf. */
1048 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
1049 if (!data_blob_realloc(NULL, &state->reply_pdu,
1050 state->reply_pdu_offset + rdata.length)) {
1052 * TODO: do a real async disconnect ...
1054 * For now do it sync...
1056 TALLOC_FREE(state->cli->transport);
1057 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1062 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
1063 rdata.data, rdata.length);
1064 state->reply_pdu_offset += rdata.length;
1066 /* reset state->incoming_frag, there is no need to free it,
1067 * it will be reallocated to the right size the next time
1069 state->incoming_frag.length = 0;
1071 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1072 /* make sure the pdu length is right now that we
1073 * have all the data available (alloc hint may
1074 * have allocated more than was actually used) */
1075 state->reply_pdu.length = state->reply_pdu_offset;
1076 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1077 rpccli_pipe_txt(talloc_tos(), state->cli),
1078 (unsigned)state->reply_pdu.length));
1079 tevent_req_done(req);
1083 subreq = get_complete_frag_send(state, state->ev, state->cli,
1084 &state->incoming_frag);
1085 if (subreq == NULL) {
1087 * TODO: do a real async disconnect ...
1089 * For now do it sync...
1091 TALLOC_FREE(state->cli->transport);
1093 if (tevent_req_nomem(subreq, req)) {
1096 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1099 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1100 struct ncacn_packet **pkt,
1101 DATA_BLOB *reply_pdu)
1103 struct rpc_api_pipe_state *state = tevent_req_data(
1104 req, struct rpc_api_pipe_state);
1107 if (tevent_req_is_nterror(req, &status)) {
1111 /* return data to caller and assign it ownership of memory */
1113 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1114 reply_pdu->length = state->reply_pdu.length;
1115 state->reply_pdu.length = 0;
1117 data_blob_free(&state->reply_pdu);
1121 *pkt = talloc_steal(mem_ctx, state->pkt);
1124 return NT_STATUS_OK;
1127 /*******************************************************************
1128 Creates NTLMSSP auth bind.
1129 ********************************************************************/
1131 static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1132 TALLOC_CTX *mem_ctx,
1133 DATA_BLOB *auth_token,
1134 bool *client_hdr_signing)
1136 struct gensec_security *gensec_security;
1137 DATA_BLOB null_blob = data_blob_null;
1140 gensec_security = cli->auth->auth_ctx;
1142 DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
1143 status = gensec_update(gensec_security, mem_ctx, null_blob, auth_token);
1145 if (!NT_STATUS_IS_OK(status) &&
1146 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1151 if (client_hdr_signing == NULL) {
1155 if (cli->auth->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1156 *client_hdr_signing = false;
1160 *client_hdr_signing = gensec_have_feature(gensec_security,
1161 GENSEC_FEATURE_SIGN_PKT_HEADER);
1166 /*******************************************************************
1167 Creates the internals of a DCE/RPC bind request or alter context PDU.
1168 ********************************************************************/
1170 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1171 enum dcerpc_pkt_type ptype,
1172 uint32_t rpc_call_id,
1173 const struct ndr_syntax_id *abstract,
1174 const struct ndr_syntax_id *transfer,
1175 const DATA_BLOB *auth_info,
1176 bool client_hdr_signing,
1179 uint16_t auth_len = auth_info->length;
1181 union dcerpc_payload u;
1182 struct dcerpc_ctx_list ctx_list;
1183 uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1186 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1189 if (client_hdr_signing) {
1190 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1193 ctx_list.context_id = 0;
1194 ctx_list.num_transfer_syntaxes = 1;
1195 ctx_list.abstract_syntax = *abstract;
1196 ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1198 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1199 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1200 u.bind.assoc_group_id = 0x0;
1201 u.bind.num_contexts = 1;
1202 u.bind.ctx_list = &ctx_list;
1203 u.bind.auth_info = *auth_info;
1205 status = dcerpc_push_ncacn_packet(mem_ctx,
1211 if (!NT_STATUS_IS_OK(status)) {
1212 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1216 return NT_STATUS_OK;
1219 /*******************************************************************
1220 Creates a DCE/RPC bind request.
1221 ********************************************************************/
1223 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1224 struct rpc_pipe_client *cli,
1225 struct pipe_auth_data *auth,
1226 uint32_t rpc_call_id,
1227 const struct ndr_syntax_id *abstract,
1228 const struct ndr_syntax_id *transfer,
1231 DATA_BLOB auth_token = data_blob_null;
1232 DATA_BLOB auth_info = data_blob_null;
1233 NTSTATUS ret = NT_STATUS_OK;
1235 switch (auth->auth_type) {
1236 case DCERPC_AUTH_TYPE_NONE:
1240 ret = create_generic_auth_rpc_bind_req(cli, mem_ctx,
1242 &auth->client_hdr_signing);
1244 if (!NT_STATUS_IS_OK(ret) &&
1245 !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1251 if (auth_token.length != 0) {
1252 ret = dcerpc_push_dcerpc_auth(cli,
1255 0, /* auth_pad_length */
1256 auth->auth_context_id,
1259 if (!NT_STATUS_IS_OK(ret)) {
1262 data_blob_free(&auth_token);
1265 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1271 auth->client_hdr_signing,
1276 /*******************************************************************
1278 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1279 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1280 and deals with signing/sealing details.
1281 ********************************************************************/
1283 struct rpc_api_pipe_req_state {
1284 struct tevent_context *ev;
1285 struct rpc_pipe_client *cli;
1288 const DATA_BLOB *req_data;
1289 const struct GUID *object_uuid;
1290 uint32_t req_data_sent;
1291 DATA_BLOB req_trailer;
1292 uint32_t req_trailer_sent;
1293 bool verify_bitmask1;
1294 bool verify_pcontext;
1296 DATA_BLOB reply_pdu;
1299 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1300 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1301 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state);
1302 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1303 bool *is_last_frag);
1305 static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1306 struct tevent_context *ev,
1307 struct rpc_pipe_client *cli,
1309 const struct GUID *object_uuid,
1310 const DATA_BLOB *req_data)
1312 struct tevent_req *req, *subreq;
1313 struct rpc_api_pipe_req_state *state;
1317 req = tevent_req_create(mem_ctx, &state,
1318 struct rpc_api_pipe_req_state);
1324 state->op_num = op_num;
1325 state->object_uuid = object_uuid;
1326 state->req_data = req_data;
1327 state->req_data_sent = 0;
1328 state->call_id = get_rpc_call_id();
1329 state->reply_pdu = data_blob_null;
1330 state->rpc_out = data_blob_null;
1332 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1333 + RPC_MAX_SIGN_SIZE) {
1334 /* Server is screwed up ! */
1335 status = NT_STATUS_INVALID_PARAMETER;
1339 status = prepare_verification_trailer(state);
1340 if (!NT_STATUS_IS_OK(status)) {
1344 status = prepare_next_frag(state, &is_last_frag);
1345 if (!NT_STATUS_IS_OK(status)) {
1350 subreq = rpc_api_pipe_send(state, ev, state->cli,
1352 DCERPC_PKT_RESPONSE,
1354 if (subreq == NULL) {
1357 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1359 subreq = rpc_write_send(state, ev, cli->transport,
1360 state->rpc_out.data,
1361 state->rpc_out.length);
1362 if (subreq == NULL) {
1365 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1371 tevent_req_nterror(req, status);
1372 return tevent_req_post(req, ev);
1378 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state)
1380 struct pipe_auth_data *a = state->cli->auth;
1381 struct dcerpc_sec_verification_trailer *t;
1382 struct dcerpc_sec_vt *c = NULL;
1383 struct ndr_push *ndr = NULL;
1384 enum ndr_err_code ndr_err;
1389 return NT_STATUS_OK;
1392 if (a->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1393 return NT_STATUS_OK;
1396 t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1398 return NT_STATUS_NO_MEMORY;
1401 if (!a->verified_bitmask1) {
1402 t->commands = talloc_realloc(t, t->commands,
1403 struct dcerpc_sec_vt,
1404 t->count.count + 1);
1405 if (t->commands == NULL) {
1406 return NT_STATUS_NO_MEMORY;
1408 c = &t->commands[t->count.count++];
1411 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1412 if (a->client_hdr_signing) {
1413 c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1415 state->verify_bitmask1 = true;
1418 if (!state->cli->verified_pcontext) {
1419 t->commands = talloc_realloc(t, t->commands,
1420 struct dcerpc_sec_vt,
1421 t->count.count + 1);
1422 if (t->commands == NULL) {
1423 return NT_STATUS_NO_MEMORY;
1425 c = &t->commands[t->count.count++];
1428 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1429 c->u.pcontext.abstract_syntax = state->cli->abstract_syntax;
1430 c->u.pcontext.transfer_syntax = state->cli->transfer_syntax;
1432 state->verify_pcontext = true;
1435 if (!a->hdr_signing) {
1436 t->commands = talloc_realloc(t, t->commands,
1437 struct dcerpc_sec_vt,
1438 t->count.count + 1);
1439 if (t->commands == NULL) {
1440 return NT_STATUS_NO_MEMORY;
1442 c = &t->commands[t->count.count++];
1445 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1446 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1447 c->u.header2.drep[0] = DCERPC_DREP_LE;
1448 c->u.header2.drep[1] = 0;
1449 c->u.header2.drep[2] = 0;
1450 c->u.header2.drep[3] = 0;
1451 c->u.header2.call_id = state->call_id;
1452 c->u.header2.context_id = 0;
1453 c->u.header2.opnum = state->op_num;
1456 if (t->count.count == 0) {
1458 return NT_STATUS_OK;
1461 c = &t->commands[t->count.count - 1];
1462 c->command |= DCERPC_SEC_VT_COMMAND_END;
1464 if (DEBUGLEVEL >= 10) {
1465 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1468 ndr = ndr_push_init_ctx(state);
1470 return NT_STATUS_NO_MEMORY;
1473 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1474 NDR_SCALARS | NDR_BUFFERS,
1476 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1477 return ndr_map_error2ntstatus(ndr_err);
1479 state->req_trailer = ndr_push_blob(ndr);
1481 align = state->req_data->length & 0x3;
1488 const uint8_t zeros[4] = { 0, };
1490 ok = data_blob_append(ndr, &state->req_trailer, zeros, pad);
1492 return NT_STATUS_NO_MEMORY;
1495 /* move the padding to the start */
1496 p = state->req_trailer.data;
1497 memmove(p + pad, p, state->req_trailer.length - pad);
1501 return NT_STATUS_OK;
1504 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1512 size_t data_thistime;
1513 size_t trailer_left;
1514 size_t trailer_thistime = 0;
1516 size_t total_thistime;
1519 union dcerpc_payload u;
1521 data_left = state->req_data->length - state->req_data_sent;
1522 trailer_left = state->req_trailer.length - state->req_trailer_sent;
1523 total_left = data_left + trailer_left;
1524 if ((total_left < data_left) || (total_left < trailer_left)) {
1528 return NT_STATUS_INVALID_PARAMETER_MIX;
1531 status = dcerpc_guess_sizes(state->cli->auth,
1532 DCERPC_REQUEST_LENGTH, total_left,
1533 state->cli->max_xmit_frag,
1535 &frag_len, &auth_len, &pad_len);
1536 if (!NT_STATUS_IS_OK(status)) {
1540 if (state->req_data_sent == 0) {
1541 flags = DCERPC_PFC_FLAG_FIRST;
1544 if (total_thistime == total_left) {
1545 flags |= DCERPC_PFC_FLAG_LAST;
1548 data_thistime = MIN(total_thistime, data_left);
1549 if (data_thistime < total_thistime) {
1550 trailer_thistime = total_thistime - data_thistime;
1553 data_blob_free(&state->rpc_out);
1555 ZERO_STRUCT(u.request);
1557 u.request.alloc_hint = total_left;
1558 u.request.context_id = 0;
1559 u.request.opnum = state->op_num;
1561 if (state->object_uuid) {
1562 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1563 u.request.object.object = *state->object_uuid;
1564 frag_len += ndr_size_GUID(state->object_uuid, 0);
1567 status = dcerpc_push_ncacn_packet(state,
1574 if (!NT_STATUS_IS_OK(status)) {
1578 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1579 * compute it right for requests because the auth trailer is missing
1581 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1583 if (data_thistime > 0) {
1584 /* Copy in the data. */
1585 ok = data_blob_append(NULL, &state->rpc_out,
1586 state->req_data->data + state->req_data_sent,
1589 return NT_STATUS_NO_MEMORY;
1591 state->req_data_sent += data_thistime;
1594 if (trailer_thistime > 0) {
1595 /* Copy in the verification trailer. */
1596 ok = data_blob_append(NULL, &state->rpc_out,
1597 state->req_trailer.data + state->req_trailer_sent,
1600 return NT_STATUS_NO_MEMORY;
1602 state->req_trailer_sent += trailer_thistime;
1605 switch (state->cli->auth->auth_level) {
1606 case DCERPC_AUTH_LEVEL_NONE:
1607 case DCERPC_AUTH_LEVEL_CONNECT:
1609 case DCERPC_AUTH_LEVEL_PACKET:
1610 case DCERPC_AUTH_LEVEL_INTEGRITY:
1611 case DCERPC_AUTH_LEVEL_PRIVACY:
1612 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1614 if (!NT_STATUS_IS_OK(status)) {
1619 return NT_STATUS_INVALID_PARAMETER;
1622 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1627 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1629 struct tevent_req *req = tevent_req_callback_data(
1630 subreq, struct tevent_req);
1631 struct rpc_api_pipe_req_state *state = tevent_req_data(
1632 req, struct rpc_api_pipe_req_state);
1636 status = rpc_write_recv(subreq);
1637 TALLOC_FREE(subreq);
1638 if (!NT_STATUS_IS_OK(status)) {
1639 tevent_req_nterror(req, status);
1643 status = prepare_next_frag(state, &is_last_frag);
1644 if (!NT_STATUS_IS_OK(status)) {
1645 tevent_req_nterror(req, status);
1650 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1652 DCERPC_PKT_RESPONSE,
1654 if (tevent_req_nomem(subreq, req)) {
1657 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1659 subreq = rpc_write_send(state, state->ev,
1660 state->cli->transport,
1661 state->rpc_out.data,
1662 state->rpc_out.length);
1663 if (tevent_req_nomem(subreq, req)) {
1666 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1671 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1673 struct tevent_req *req = tevent_req_callback_data(
1674 subreq, struct tevent_req);
1675 struct rpc_api_pipe_req_state *state = tevent_req_data(
1676 req, struct rpc_api_pipe_req_state);
1679 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1680 TALLOC_FREE(subreq);
1681 if (!NT_STATUS_IS_OK(status)) {
1682 tevent_req_nterror(req, status);
1686 if (state->cli->auth == NULL) {
1687 tevent_req_done(req);
1691 if (state->verify_bitmask1) {
1692 state->cli->auth->verified_bitmask1 = true;
1695 if (state->verify_pcontext) {
1696 state->cli->verified_pcontext = true;
1699 tevent_req_done(req);
1702 static NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1703 DATA_BLOB *reply_pdu)
1705 struct rpc_api_pipe_req_state *state = tevent_req_data(
1706 req, struct rpc_api_pipe_req_state);
1709 if (tevent_req_is_nterror(req, &status)) {
1711 * We always have to initialize to reply pdu, even if there is
1712 * none. The rpccli_* caller routines expect this.
1714 *reply_pdu = data_blob_null;
1718 /* return data to caller and assign it ownership of memory */
1719 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1720 reply_pdu->length = state->reply_pdu.length;
1721 state->reply_pdu.length = 0;
1723 return NT_STATUS_OK;
1726 /****************************************************************************
1727 Check the rpc bind acknowledge response.
1728 ****************************************************************************/
1730 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1731 const struct ndr_syntax_id *transfer)
1733 struct dcerpc_ack_ctx ctx;
1735 if (r->secondary_address_size == 0) {
1736 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1739 if (r->num_results < 1 || !r->ctx_list) {
1743 ctx = r->ctx_list[0];
1745 /* check the transfer syntax */
1746 if ((ctx.syntax.if_version != transfer->if_version) ||
1747 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1748 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1752 if (r->num_results != 0x1 || ctx.result != 0) {
1753 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1754 r->num_results, ctx.reason.value));
1757 DEBUG(5,("check_bind_response: accepted!\n"));
1761 /*******************************************************************
1762 Creates a DCE/RPC bind authentication response.
1763 This is the packet that is sent back to the server once we
1764 have received a BIND-ACK, to finish the third leg of
1765 the authentication handshake.
1766 ********************************************************************/
1768 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1769 struct rpc_pipe_client *cli,
1770 struct pipe_auth_data *auth,
1771 uint32_t rpc_call_id,
1772 DATA_BLOB *pauth_blob,
1776 union dcerpc_payload u;
1780 status = dcerpc_push_dcerpc_auth(mem_ctx,
1783 0, /* auth_pad_length */
1784 auth->auth_context_id,
1786 &u.auth3.auth_info);
1787 if (!NT_STATUS_IS_OK(status)) {
1791 status = dcerpc_push_ncacn_packet(mem_ctx,
1793 DCERPC_PFC_FLAG_FIRST |
1794 DCERPC_PFC_FLAG_LAST,
1799 data_blob_free(&u.auth3.auth_info);
1800 if (!NT_STATUS_IS_OK(status)) {
1801 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1805 return NT_STATUS_OK;
1808 /*******************************************************************
1809 Creates a DCE/RPC bind alter context authentication request which
1810 may contain a spnego auth blobl
1811 ********************************************************************/
1813 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1814 struct pipe_auth_data *auth,
1815 uint32_t rpc_call_id,
1816 const struct ndr_syntax_id *abstract,
1817 const struct ndr_syntax_id *transfer,
1818 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1821 DATA_BLOB auth_info;
1824 status = dcerpc_push_dcerpc_auth(mem_ctx,
1827 0, /* auth_pad_length */
1828 auth->auth_context_id,
1831 if (!NT_STATUS_IS_OK(status)) {
1835 status = create_bind_or_alt_ctx_internal(mem_ctx,
1841 false, /* client_hdr_signing */
1843 data_blob_free(&auth_info);
1847 /****************************************************************************
1849 ****************************************************************************/
1851 struct rpc_pipe_bind_state {
1852 struct tevent_context *ev;
1853 struct rpc_pipe_client *cli;
1856 uint32_t rpc_call_id;
1859 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1860 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1861 struct rpc_pipe_bind_state *state,
1862 DATA_BLOB *credentials);
1863 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1864 struct rpc_pipe_bind_state *state,
1865 DATA_BLOB *credentials);
1867 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1868 struct tevent_context *ev,
1869 struct rpc_pipe_client *cli,
1870 struct pipe_auth_data *auth)
1872 struct tevent_req *req, *subreq;
1873 struct rpc_pipe_bind_state *state;
1876 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1881 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1882 rpccli_pipe_txt(talloc_tos(), cli),
1883 (unsigned int)auth->auth_type,
1884 (unsigned int)auth->auth_level ));
1888 state->rpc_call_id = get_rpc_call_id();
1890 cli->auth = talloc_move(cli, &auth);
1892 /* Marshall the outgoing data. */
1893 status = create_rpc_bind_req(state, cli,
1896 &cli->abstract_syntax,
1897 &cli->transfer_syntax,
1900 if (!NT_STATUS_IS_OK(status) &&
1901 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1905 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1906 DCERPC_PKT_BIND_ACK, state->rpc_call_id);
1907 if (subreq == NULL) {
1910 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1914 tevent_req_nterror(req, status);
1915 return tevent_req_post(req, ev);
1921 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1923 struct tevent_req *req = tevent_req_callback_data(
1924 subreq, struct tevent_req);
1925 struct rpc_pipe_bind_state *state = tevent_req_data(
1926 req, struct rpc_pipe_bind_state);
1927 struct pipe_auth_data *pauth = state->cli->auth;
1928 struct gensec_security *gensec_security;
1929 struct ncacn_packet *pkt = NULL;
1930 struct dcerpc_auth auth;
1931 DATA_BLOB auth_token = data_blob_null;
1934 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
1935 TALLOC_FREE(subreq);
1936 if (!NT_STATUS_IS_OK(status)) {
1937 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1938 rpccli_pipe_txt(talloc_tos(), state->cli),
1939 nt_errstr(status)));
1940 tevent_req_nterror(req, status);
1945 tevent_req_done(req);
1949 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1950 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1951 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1955 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1957 switch(pauth->auth_type) {
1959 case DCERPC_AUTH_TYPE_NONE:
1960 /* Bind complete. */
1961 tevent_req_done(req);
1965 if (pkt->auth_length == 0) {
1966 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1970 /* get auth credentials */
1971 status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
1972 &pkt->u.bind_ack.auth_info,
1974 if (!NT_STATUS_IS_OK(status)) {
1975 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1976 nt_errstr(status)));
1977 tevent_req_nterror(req, status);
1981 if (auth.auth_type != pauth->auth_type) {
1982 DEBUG(0, (__location__ " Auth type %u mismatch expected %u.\n",
1983 auth.auth_type, pauth->auth_type));
1984 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1988 if (auth.auth_level != pauth->auth_level) {
1989 DEBUG(0, (__location__ " Auth level %u mismatch expected %u.\n",
1990 auth.auth_level, pauth->auth_level));
1991 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1995 if (auth.auth_context_id != pauth->auth_context_id) {
1996 DEBUG(0, (__location__ " Auth context id %u mismatch expected %u.\n",
1997 (unsigned)auth.auth_context_id,
1998 (unsigned)pauth->auth_context_id));
1999 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
2007 * For authenticated binds we may need to do 3 or 4 leg binds.
2010 switch(pauth->auth_type) {
2012 case DCERPC_AUTH_TYPE_NONE:
2013 /* Bind complete. */
2014 tevent_req_done(req);
2018 gensec_security = pauth->auth_ctx;
2020 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
2021 if (pauth->client_hdr_signing) {
2022 pauth->hdr_signing = true;
2023 gensec_want_feature(gensec_security,
2024 GENSEC_FEATURE_SIGN_PKT_HEADER);
2028 status = gensec_update(gensec_security, state,
2029 auth.credentials, &auth_token);
2030 if (NT_STATUS_EQUAL(status,
2031 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2032 status = rpc_bind_next_send(req, state,
2034 } else if (NT_STATUS_IS_OK(status)) {
2035 if (auth_token.length == 0) {
2036 /* Bind complete. */
2037 tevent_req_done(req);
2040 status = rpc_bind_finish_send(req, state,
2046 if (!NT_STATUS_IS_OK(status)) {
2047 tevent_req_nterror(req, status);
2052 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
2053 struct rpc_pipe_bind_state *state,
2054 DATA_BLOB *auth_token)
2056 struct pipe_auth_data *auth = state->cli->auth;
2057 struct tevent_req *subreq;
2060 /* Now prepare the alter context pdu. */
2061 data_blob_free(&state->rpc_out);
2063 status = create_rpc_alter_context(state, auth,
2065 &state->cli->abstract_syntax,
2066 &state->cli->transfer_syntax,
2069 if (!NT_STATUS_IS_OK(status)) {
2073 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2074 &state->rpc_out, DCERPC_PKT_ALTER_RESP,
2075 state->rpc_call_id);
2076 if (subreq == NULL) {
2077 return NT_STATUS_NO_MEMORY;
2079 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2080 return NT_STATUS_OK;
2083 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
2084 struct rpc_pipe_bind_state *state,
2085 DATA_BLOB *auth_token)
2087 struct pipe_auth_data *auth = state->cli->auth;
2088 struct tevent_req *subreq;
2091 state->auth3 = true;
2093 /* Now prepare the auth3 context pdu. */
2094 data_blob_free(&state->rpc_out);
2096 status = create_rpc_bind_auth3(state, state->cli, auth,
2100 if (!NT_STATUS_IS_OK(status)) {
2104 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2105 &state->rpc_out, DCERPC_PKT_AUTH3,
2106 state->rpc_call_id);
2107 if (subreq == NULL) {
2108 return NT_STATUS_NO_MEMORY;
2110 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2111 return NT_STATUS_OK;
2114 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2116 return tevent_req_simple_recv_ntstatus(req);
2119 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2120 struct pipe_auth_data *auth)
2122 TALLOC_CTX *frame = talloc_stackframe();
2123 struct tevent_context *ev;
2124 struct tevent_req *req;
2125 NTSTATUS status = NT_STATUS_OK;
2127 ev = samba_tevent_context_init(frame);
2129 status = NT_STATUS_NO_MEMORY;
2133 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2135 status = NT_STATUS_NO_MEMORY;
2139 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2143 status = rpc_pipe_bind_recv(req);
2149 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2151 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2152 unsigned int timeout)
2156 if (rpc_cli->transport == NULL) {
2157 return RPCCLI_DEFAULT_TIMEOUT;
2160 if (rpc_cli->transport->set_timeout == NULL) {
2161 return RPCCLI_DEFAULT_TIMEOUT;
2164 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2166 return RPCCLI_DEFAULT_TIMEOUT;
2172 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2174 if (rpc_cli == NULL) {
2178 if (rpc_cli->transport == NULL) {
2182 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2185 struct rpccli_bh_state {
2186 struct rpc_pipe_client *rpc_cli;
2189 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2191 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2192 struct rpccli_bh_state);
2194 return rpccli_is_connected(hs->rpc_cli);
2197 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2200 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2201 struct rpccli_bh_state);
2203 return rpccli_set_timeout(hs->rpc_cli, timeout);
2206 static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
2207 enum dcerpc_AuthType *auth_type,
2208 enum dcerpc_AuthLevel *auth_level)
2210 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2211 struct rpccli_bh_state);
2213 if (hs->rpc_cli == NULL) {
2217 if (hs->rpc_cli->auth == NULL) {
2221 *auth_type = hs->rpc_cli->auth->auth_type;
2222 *auth_level = hs->rpc_cli->auth->auth_level;
2225 struct rpccli_bh_raw_call_state {
2231 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2233 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2234 struct tevent_context *ev,
2235 struct dcerpc_binding_handle *h,
2236 const struct GUID *object,
2239 const uint8_t *in_data,
2242 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2243 struct rpccli_bh_state);
2244 struct tevent_req *req;
2245 struct rpccli_bh_raw_call_state *state;
2247 struct tevent_req *subreq;
2249 req = tevent_req_create(mem_ctx, &state,
2250 struct rpccli_bh_raw_call_state);
2254 state->in_data.data = discard_const_p(uint8_t, in_data);
2255 state->in_data.length = in_length;
2257 ok = rpccli_bh_is_connected(h);
2259 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2260 return tevent_req_post(req, ev);
2263 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2264 opnum, object, &state->in_data);
2265 if (tevent_req_nomem(subreq, req)) {
2266 return tevent_req_post(req, ev);
2268 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2273 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2275 struct tevent_req *req =
2276 tevent_req_callback_data(subreq,
2278 struct rpccli_bh_raw_call_state *state =
2279 tevent_req_data(req,
2280 struct rpccli_bh_raw_call_state);
2283 state->out_flags = 0;
2285 /* TODO: support bigendian responses */
2287 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2288 TALLOC_FREE(subreq);
2289 if (!NT_STATUS_IS_OK(status)) {
2290 tevent_req_nterror(req, status);
2294 tevent_req_done(req);
2297 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2298 TALLOC_CTX *mem_ctx,
2301 uint32_t *out_flags)
2303 struct rpccli_bh_raw_call_state *state =
2304 tevent_req_data(req,
2305 struct rpccli_bh_raw_call_state);
2308 if (tevent_req_is_nterror(req, &status)) {
2309 tevent_req_received(req);
2313 *out_data = talloc_move(mem_ctx, &state->out_data.data);
2314 *out_length = state->out_data.length;
2315 *out_flags = state->out_flags;
2316 tevent_req_received(req);
2317 return NT_STATUS_OK;
2320 struct rpccli_bh_disconnect_state {
2324 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2325 struct tevent_context *ev,
2326 struct dcerpc_binding_handle *h)
2328 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2329 struct rpccli_bh_state);
2330 struct tevent_req *req;
2331 struct rpccli_bh_disconnect_state *state;
2334 req = tevent_req_create(mem_ctx, &state,
2335 struct rpccli_bh_disconnect_state);
2340 ok = rpccli_bh_is_connected(h);
2342 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2343 return tevent_req_post(req, ev);
2347 * TODO: do a real async disconnect ...
2349 * For now we do it sync...
2351 TALLOC_FREE(hs->rpc_cli->transport);
2354 tevent_req_done(req);
2355 return tevent_req_post(req, ev);
2358 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2362 if (tevent_req_is_nterror(req, &status)) {
2363 tevent_req_received(req);
2367 tevent_req_received(req);
2368 return NT_STATUS_OK;
2371 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2376 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2378 const void *_struct_ptr,
2379 const struct ndr_interface_call *call)
2381 void *struct_ptr = discard_const(_struct_ptr);
2383 if (DEBUGLEVEL < 10) {
2387 if (ndr_flags & NDR_IN) {
2388 ndr_print_function_debug(call->ndr_print,
2393 if (ndr_flags & NDR_OUT) {
2394 ndr_print_function_debug(call->ndr_print,
2401 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2403 .is_connected = rpccli_bh_is_connected,
2404 .set_timeout = rpccli_bh_set_timeout,
2405 .auth_info = rpccli_bh_auth_info,
2406 .raw_call_send = rpccli_bh_raw_call_send,
2407 .raw_call_recv = rpccli_bh_raw_call_recv,
2408 .disconnect_send = rpccli_bh_disconnect_send,
2409 .disconnect_recv = rpccli_bh_disconnect_recv,
2411 .ref_alloc = rpccli_bh_ref_alloc,
2412 .do_ndr_print = rpccli_bh_do_ndr_print,
2415 /* initialise a rpc_pipe_client binding handle */
2416 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2417 const struct GUID *object,
2418 const struct ndr_interface_table *table)
2420 struct dcerpc_binding_handle *h;
2421 struct rpccli_bh_state *hs;
2423 h = dcerpc_binding_handle_create(c,
2428 struct rpccli_bh_state,
2438 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2439 struct pipe_auth_data **presult)
2441 struct pipe_auth_data *result;
2442 struct auth_generic_state *auth_generic_ctx;
2445 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2446 if (result == NULL) {
2447 return NT_STATUS_NO_MEMORY;
2450 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2451 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2452 result->auth_context_id = 0;
2454 status = auth_generic_client_prepare(result,
2456 if (!NT_STATUS_IS_OK(status)) {
2457 DEBUG(1, ("Failed to create auth_generic context: %s\n",
2458 nt_errstr(status)));
2461 status = auth_generic_set_username(auth_generic_ctx, "");
2462 if (!NT_STATUS_IS_OK(status)) {
2463 DEBUG(1, ("Failed to set username: %s\n",
2464 nt_errstr(status)));
2467 status = auth_generic_set_domain(auth_generic_ctx, "");
2468 if (!NT_STATUS_IS_OK(status)) {
2469 DEBUG(1, ("Failed to set domain: %s\n",
2470 nt_errstr(status)));
2474 status = gensec_set_credentials(auth_generic_ctx->gensec_security,
2475 auth_generic_ctx->credentials);
2476 if (!NT_STATUS_IS_OK(status)) {
2477 DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
2478 nt_errstr(status)));
2481 talloc_unlink(auth_generic_ctx, auth_generic_ctx->credentials);
2482 auth_generic_ctx->credentials = NULL;
2484 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2485 talloc_free(auth_generic_ctx);
2487 return NT_STATUS_OK;
2490 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2491 enum dcerpc_AuthType auth_type,
2492 enum dcerpc_AuthLevel auth_level,
2494 const char *target_service,
2496 const char *username,
2497 const char *password,
2498 enum credentials_use_kerberos use_kerberos,
2499 struct netlogon_creds_CredentialState *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_username(auth_generic_ctx, username);
2522 if (!NT_STATUS_IS_OK(status)) {
2526 status = auth_generic_set_domain(auth_generic_ctx, domain);
2527 if (!NT_STATUS_IS_OK(status)) {
2531 status = auth_generic_set_password(auth_generic_ctx, password);
2532 if (!NT_STATUS_IS_OK(status)) {
2536 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2537 if (!NT_STATUS_IS_OK(status)) {
2541 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2542 if (!NT_STATUS_IS_OK(status)) {
2546 cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos);
2547 cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
2549 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2550 if (!NT_STATUS_IS_OK(status)) {
2554 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2555 talloc_free(auth_generic_ctx);
2557 return NT_STATUS_OK;
2560 TALLOC_FREE(result);
2564 /* This routine steals the creds pointer that is passed in */
2565 static NTSTATUS rpccli_generic_bind_data_from_creds(TALLOC_CTX *mem_ctx,
2566 enum dcerpc_AuthType auth_type,
2567 enum dcerpc_AuthLevel auth_level,
2569 const char *target_service,
2570 struct cli_credentials *creds,
2571 struct pipe_auth_data **presult)
2573 struct auth_generic_state *auth_generic_ctx;
2574 struct pipe_auth_data *result;
2577 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2578 if (result == NULL) {
2579 return NT_STATUS_NO_MEMORY;
2582 result->auth_type = auth_type;
2583 result->auth_level = auth_level;
2584 result->auth_context_id = 1;
2586 status = auth_generic_client_prepare(result,
2588 if (!NT_STATUS_IS_OK(status)) {
2592 status = auth_generic_set_creds(auth_generic_ctx, creds);
2593 if (!NT_STATUS_IS_OK(status)) {
2597 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2598 if (!NT_STATUS_IS_OK(status)) {
2602 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2603 if (!NT_STATUS_IS_OK(status)) {
2607 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2608 if (!NT_STATUS_IS_OK(status)) {
2612 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2613 talloc_free(auth_generic_ctx);
2615 return NT_STATUS_OK;
2618 TALLOC_FREE(result);
2622 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2623 struct pipe_auth_data **presult)
2625 return rpccli_generic_bind_data(mem_ctx,
2626 DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
2627 DCERPC_AUTH_LEVEL_CONNECT,
2629 "host", /* target_service */
2630 NAME_NT_AUTHORITY, /* domain */
2632 NULL, /* password */
2633 CRED_DONT_USE_KERBEROS,
2634 NULL, /* netlogon_creds_CredentialState */
2639 * Create an rpc pipe client struct, connecting to a tcp port.
2641 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2642 const struct sockaddr_storage *ss_addr,
2644 const struct ndr_interface_table *table,
2645 struct rpc_pipe_client **presult)
2647 struct rpc_pipe_client *result;
2648 struct sockaddr_storage addr;
2652 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2653 if (result == NULL) {
2654 return NT_STATUS_NO_MEMORY;
2657 result->abstract_syntax = table->syntax_id;
2658 result->transfer_syntax = ndr_transfer_syntax_ndr;
2660 result->desthost = talloc_strdup(result, host);
2661 result->srv_name_slash = talloc_asprintf_strupper_m(
2662 result, "\\\\%s", result->desthost);
2663 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2664 status = NT_STATUS_NO_MEMORY;
2668 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2670 if (ss_addr == NULL) {
2671 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2672 status = NT_STATUS_NOT_FOUND;
2679 status = open_socket_out(&addr, port, 60*1000, &fd);
2680 if (!NT_STATUS_IS_OK(status)) {
2683 set_socket_options(fd, lp_socket_options());
2685 status = rpc_transport_sock_init(result, fd, &result->transport);
2686 if (!NT_STATUS_IS_OK(status)) {
2691 result->transport->transport = NCACN_IP_TCP;
2693 result->binding_handle = rpccli_bh_create(result, NULL, table);
2694 if (result->binding_handle == NULL) {
2695 TALLOC_FREE(result);
2696 return NT_STATUS_NO_MEMORY;
2700 return NT_STATUS_OK;
2703 TALLOC_FREE(result);
2708 * Determine the tcp port on which a dcerpc interface is listening
2709 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2712 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2713 const struct sockaddr_storage *addr,
2714 const struct ndr_interface_table *table,
2718 struct rpc_pipe_client *epm_pipe = NULL;
2719 struct dcerpc_binding_handle *epm_handle = NULL;
2720 struct pipe_auth_data *auth = NULL;
2721 struct dcerpc_binding *map_binding = NULL;
2722 struct dcerpc_binding *res_binding = NULL;
2723 enum dcerpc_transport_t transport;
2724 const char *endpoint = NULL;
2725 struct epm_twr_t *map_tower = NULL;
2726 struct epm_twr_t *res_towers = NULL;
2727 struct policy_handle *entry_handle = NULL;
2728 uint32_t num_towers = 0;
2729 uint32_t max_towers = 1;
2730 struct epm_twr_p_t towers;
2731 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2732 uint32_t result = 0;
2734 if (pport == NULL) {
2735 status = NT_STATUS_INVALID_PARAMETER;
2739 if (ndr_syntax_id_equal(&table->syntax_id,
2740 &ndr_table_epmapper.syntax_id)) {
2742 status = NT_STATUS_OK;
2746 /* open the connection to the endpoint mapper */
2747 status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2748 &ndr_table_epmapper,
2751 if (!NT_STATUS_IS_OK(status)) {
2754 epm_handle = epm_pipe->binding_handle;
2756 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2757 if (!NT_STATUS_IS_OK(status)) {
2761 status = rpc_pipe_bind(epm_pipe, auth);
2762 if (!NT_STATUS_IS_OK(status)) {
2766 /* create tower for asking the epmapper */
2768 status = dcerpc_parse_binding(tmp_ctx, "ncacn_ip_tcp:[135]",
2770 if (!NT_STATUS_IS_OK(status)) {
2774 status = dcerpc_binding_set_abstract_syntax(map_binding,
2776 if (!NT_STATUS_IS_OK(status)) {
2780 map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
2781 if (map_tower == NULL) {
2782 status = NT_STATUS_NO_MEMORY;
2786 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2787 &(map_tower->tower));
2788 if (!NT_STATUS_IS_OK(status)) {
2792 /* allocate further parameters for the epm_Map call */
2794 res_towers = talloc_array(tmp_ctx, struct epm_twr_t, max_towers);
2795 if (res_towers == NULL) {
2796 status = NT_STATUS_NO_MEMORY;
2799 towers.twr = res_towers;
2801 entry_handle = talloc_zero(tmp_ctx, struct policy_handle);
2802 if (entry_handle == NULL) {
2803 status = NT_STATUS_NO_MEMORY;
2807 /* ask the endpoint mapper for the port */
2809 status = dcerpc_epm_Map(epm_handle,
2811 discard_const_p(struct GUID,
2812 &(table->syntax_id.uuid)),
2820 if (!NT_STATUS_IS_OK(status)) {
2824 if (result != EPMAPPER_STATUS_OK) {
2825 status = NT_STATUS_UNSUCCESSFUL;
2829 if (num_towers != 1) {
2830 status = NT_STATUS_UNSUCCESSFUL;
2834 /* extract the port from the answer */
2836 status = dcerpc_binding_from_tower(tmp_ctx,
2837 &(towers.twr->tower),
2839 if (!NT_STATUS_IS_OK(status)) {
2843 transport = dcerpc_binding_get_transport(res_binding);
2844 endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
2846 /* are further checks here necessary? */
2847 if (transport != NCACN_IP_TCP) {
2848 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2852 if (endpoint == NULL) {
2853 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2857 *pport = (uint16_t)atoi(endpoint);
2860 TALLOC_FREE(tmp_ctx);
2865 * Create a rpc pipe client struct, connecting to a host via tcp.
2866 * The port is determined by asking the endpoint mapper on the given
2869 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2870 const struct sockaddr_storage *addr,
2871 const struct ndr_interface_table *table,
2872 struct rpc_pipe_client **presult)
2877 status = rpc_pipe_get_tcp_port(host, addr, table, &port);
2878 if (!NT_STATUS_IS_OK(status)) {
2882 return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2886 /********************************************************************
2887 Create a rpc pipe client struct, connecting to a unix domain socket
2888 ********************************************************************/
2889 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2890 const struct ndr_interface_table *table,
2891 struct rpc_pipe_client **presult)
2893 struct rpc_pipe_client *result;
2894 struct sockaddr_un addr;
2899 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2900 if (result == NULL) {
2901 return NT_STATUS_NO_MEMORY;
2904 result->abstract_syntax = table->syntax_id;
2905 result->transfer_syntax = ndr_transfer_syntax_ndr;
2907 result->desthost = get_myname(result);
2908 result->srv_name_slash = talloc_asprintf_strupper_m(
2909 result, "\\\\%s", result->desthost);
2910 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2911 status = NT_STATUS_NO_MEMORY;
2915 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2917 fd = socket(AF_UNIX, SOCK_STREAM, 0);
2919 status = map_nt_error_from_unix(errno);
2924 addr.sun_family = AF_UNIX;
2925 strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2926 salen = sizeof(struct sockaddr_un);
2928 if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
2929 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2932 return map_nt_error_from_unix(errno);
2935 status = rpc_transport_sock_init(result, fd, &result->transport);
2936 if (!NT_STATUS_IS_OK(status)) {
2941 result->transport->transport = NCALRPC;
2943 result->binding_handle = rpccli_bh_create(result, NULL, table);
2944 if (result->binding_handle == NULL) {
2945 TALLOC_FREE(result);
2946 return NT_STATUS_NO_MEMORY;
2950 return NT_STATUS_OK;
2953 TALLOC_FREE(result);
2957 struct rpc_pipe_client_np_ref {
2958 struct cli_state *cli;
2959 struct rpc_pipe_client *pipe;
2962 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2964 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2968 /****************************************************************************
2969 Open a named pipe over SMB to a remote server.
2971 * CAVEAT CALLER OF THIS FUNCTION:
2972 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2973 * so be sure that this function is called AFTER any structure (vs pointer)
2974 * assignment of the cli. In particular, libsmbclient does structure
2975 * assignments of cli, which invalidates the data in the returned
2976 * rpc_pipe_client if this function is called before the structure assignment
2979 ****************************************************************************/
2981 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2982 const struct ndr_interface_table *table,
2983 struct rpc_pipe_client **presult)
2985 struct rpc_pipe_client *result;
2987 struct rpc_pipe_client_np_ref *np_ref;
2989 /* sanity check to protect against crashes */
2992 return NT_STATUS_INVALID_HANDLE;
2995 result = talloc_zero(NULL, struct rpc_pipe_client);
2996 if (result == NULL) {
2997 return NT_STATUS_NO_MEMORY;
3000 result->abstract_syntax = table->syntax_id;
3001 result->transfer_syntax = ndr_transfer_syntax_ndr;
3002 result->desthost = talloc_strdup(result, smbXcli_conn_remote_name(cli->conn));
3003 result->srv_name_slash = talloc_asprintf_strupper_m(
3004 result, "\\\\%s", result->desthost);
3006 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3008 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3009 TALLOC_FREE(result);
3010 return NT_STATUS_NO_MEMORY;
3013 status = rpc_transport_np_init(result, cli, table,
3014 &result->transport);
3015 if (!NT_STATUS_IS_OK(status)) {
3016 TALLOC_FREE(result);
3020 result->transport->transport = NCACN_NP;
3022 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3023 if (np_ref == NULL) {
3024 TALLOC_FREE(result);
3025 return NT_STATUS_NO_MEMORY;
3028 np_ref->pipe = result;
3030 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3031 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3033 result->binding_handle = rpccli_bh_create(result, NULL, table);
3034 if (result->binding_handle == NULL) {
3035 TALLOC_FREE(result);
3036 return NT_STATUS_NO_MEMORY;
3040 return NT_STATUS_OK;
3043 /****************************************************************************
3044 Open a pipe to a remote server.
3045 ****************************************************************************/
3047 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3048 enum dcerpc_transport_t transport,
3049 const struct ndr_interface_table *table,
3050 struct rpc_pipe_client **presult)
3052 switch (transport) {
3054 return rpc_pipe_open_tcp(NULL,
3055 smbXcli_conn_remote_name(cli->conn),
3056 smbXcli_conn_remote_sockaddr(cli->conn),
3059 return rpc_pipe_open_np(cli, table, presult);
3061 return NT_STATUS_NOT_IMPLEMENTED;
3065 /****************************************************************************
3066 Open a named pipe to an SMB server and bind anonymously.
3067 ****************************************************************************/
3069 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3070 enum dcerpc_transport_t transport,
3071 const struct ndr_interface_table *table,
3072 struct rpc_pipe_client **presult)
3074 struct rpc_pipe_client *result;
3075 struct pipe_auth_data *auth;
3078 status = cli_rpc_pipe_open(cli, transport, table, &result);
3079 if (!NT_STATUS_IS_OK(status)) {
3083 status = rpccli_anon_bind_data(result, &auth);
3084 if (!NT_STATUS_IS_OK(status)) {
3085 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3086 nt_errstr(status)));
3087 TALLOC_FREE(result);
3092 * This is a bit of an abstraction violation due to the fact that an
3093 * anonymous bind on an authenticated SMB inherits the user/domain
3094 * from the enclosing SMB creds
3097 if (transport == NCACN_NP) {
3098 struct smbXcli_session *session;
3100 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3101 session = cli->smb2.session;
3103 session = cli->smb1.session;
3106 status = smbXcli_session_application_key(session, auth,
3107 &auth->transport_session_key);
3108 if (!NT_STATUS_IS_OK(status)) {
3109 auth->transport_session_key = data_blob_null;
3113 status = rpc_pipe_bind(result, auth);
3114 if (!NT_STATUS_IS_OK(status)) {
3116 if (ndr_syntax_id_equal(&table->syntax_id,
3117 &ndr_table_dssetup.syntax_id)) {
3118 /* non AD domains just don't have this pipe, avoid
3119 * level 0 statement in that case - gd */
3122 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3123 "%s failed with error %s\n",
3125 nt_errstr(status) ));
3126 TALLOC_FREE(result);
3130 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3131 "%s and bound anonymously.\n",
3136 return NT_STATUS_OK;
3139 /****************************************************************************
3140 ****************************************************************************/
3142 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3143 const struct ndr_interface_table *table,
3144 struct rpc_pipe_client **presult)
3146 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3150 /****************************************************************************
3151 Open a named pipe to an SMB server and bind using the mech specified
3153 This routine references the creds pointer that is passed in
3154 ****************************************************************************/
3156 NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
3157 const struct ndr_interface_table *table,
3158 enum dcerpc_transport_t transport,
3159 enum dcerpc_AuthType auth_type,
3160 enum dcerpc_AuthLevel auth_level,
3162 struct cli_credentials *creds,
3163 struct rpc_pipe_client **presult)
3165 struct rpc_pipe_client *result;
3166 struct pipe_auth_data *auth = NULL;
3167 const char *target_service = table->authservices->names[0];
3171 status = cli_rpc_pipe_open(cli, transport, table, &result);
3172 if (!NT_STATUS_IS_OK(status)) {
3176 status = rpccli_generic_bind_data_from_creds(result,
3177 auth_type, auth_level,
3178 server, target_service,
3181 if (!NT_STATUS_IS_OK(status)) {
3182 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3183 nt_errstr(status)));
3187 status = rpc_pipe_bind(result, auth);
3188 if (!NT_STATUS_IS_OK(status)) {
3189 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
3190 nt_errstr(status) ));
3194 DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
3195 "machine %s and bound as user %s.\n", table->name,
3196 result->desthost, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3199 return NT_STATUS_OK;
3203 TALLOC_FREE(result);
3207 /****************************************************************************
3208 Open a named pipe to an SMB server and bind using the mech specified
3210 This routine steals the creds pointer that is passed in
3211 ****************************************************************************/
3213 NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
3214 const struct ndr_interface_table *table,
3215 enum dcerpc_transport_t transport,
3216 enum credentials_use_kerberos use_kerberos,
3217 enum dcerpc_AuthType auth_type,
3218 enum dcerpc_AuthLevel auth_level,
3221 const char *username,
3222 const char *password,
3223 struct rpc_pipe_client **presult)
3225 struct rpc_pipe_client *result;
3226 struct pipe_auth_data *auth = NULL;
3227 const char *target_service = table->authservices->names[0];
3231 status = cli_rpc_pipe_open(cli, transport, table, &result);
3232 if (!NT_STATUS_IS_OK(status)) {
3236 status = rpccli_generic_bind_data(result,
3237 auth_type, auth_level,
3238 server, target_service,
3239 domain, username, password,
3240 CRED_AUTO_USE_KERBEROS,
3243 if (!NT_STATUS_IS_OK(status)) {
3244 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3245 nt_errstr(status)));
3249 status = rpc_pipe_bind(result, auth);
3250 if (!NT_STATUS_IS_OK(status)) {
3251 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
3252 nt_errstr(status) ));
3256 DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
3257 "machine %s and bound as user %s\\%s.\n", table->name,
3258 result->desthost, domain, username));
3261 return NT_STATUS_OK;
3265 TALLOC_FREE(result);
3269 NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
3270 const struct ndr_interface_table *table,
3271 enum dcerpc_transport_t transport,
3272 struct cli_credentials *cli_creds,
3273 struct netlogon_creds_cli_context *netlogon_creds,
3274 struct rpc_pipe_client **_rpccli)
3276 struct rpc_pipe_client *rpccli;
3277 struct pipe_auth_data *rpcauth;
3278 const char *target_service = table->authservices->names[0];
3279 struct netlogon_creds_CredentialState *ncreds = NULL;
3280 enum dcerpc_AuthLevel auth_level;
3282 int rpc_pipe_bind_dbglvl = 0;
3284 status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
3285 if (!NT_STATUS_IS_OK(status)) {
3289 status = netlogon_creds_cli_lock(netlogon_creds, rpccli, &ncreds);
3290 if (!NT_STATUS_IS_OK(status)) {
3291 DEBUG(0, ("netlogon_creds_cli_get returned %s\n",
3292 nt_errstr(status)));
3293 TALLOC_FREE(rpccli);
3297 auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
3299 cli_credentials_set_netlogon_creds(cli_creds, ncreds);
3301 status = rpccli_generic_bind_data_from_creds(rpccli,
3302 DCERPC_AUTH_TYPE_SCHANNEL,
3308 if (!NT_STATUS_IS_OK(status)) {
3309 DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
3310 nt_errstr(status)));
3311 TALLOC_FREE(rpccli);
3315 status = rpc_pipe_bind(rpccli, rpcauth);
3316 cli_credentials_set_netlogon_creds(cli_creds, NULL);
3317 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3318 rpc_pipe_bind_dbglvl = 1;
3319 netlogon_creds_cli_delete(netlogon_creds, &ncreds);
3321 if (!NT_STATUS_IS_OK(status)) {
3322 DEBUG(rpc_pipe_bind_dbglvl,
3323 ("%s: rpc_pipe_bind failed with error %s\n",
3324 __func__, nt_errstr(status)));
3325 TALLOC_FREE(rpccli);
3329 TALLOC_FREE(ncreds);
3331 if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) {
3335 status = netlogon_creds_cli_check(netlogon_creds,
3336 rpccli->binding_handle);
3337 if (!NT_STATUS_IS_OK(status)) {
3338 DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
3339 nt_errstr(status)));
3340 TALLOC_FREE(rpccli);
3346 DEBUG(10,("%s: opened pipe %s to machine %s "
3347 "for domain %s and bound using schannel.\n",
3348 __func__, table->name,
3349 rpccli->desthost, cli_credentials_get_domain(cli_creds)));
3352 return NT_STATUS_OK;
3355 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3356 struct rpc_pipe_client *cli,
3357 DATA_BLOB *session_key)
3360 struct pipe_auth_data *a;
3361 struct gensec_security *gensec_security;
3362 DATA_BLOB sk = data_blob_null;
3363 bool make_dup = false;
3365 if (!session_key || !cli) {
3366 return NT_STATUS_INVALID_PARAMETER;
3372 return NT_STATUS_INVALID_PARAMETER;
3375 switch (cli->auth->auth_type) {
3376 case DCERPC_AUTH_TYPE_NONE:
3377 sk = data_blob_const(a->transport_session_key.data,
3378 a->transport_session_key.length);
3382 gensec_security = a->auth_ctx;
3383 status = gensec_session_key(gensec_security, mem_ctx, &sk);
3384 if (!NT_STATUS_IS_OK(status)) {
3392 return NT_STATUS_NO_USER_SESSION_KEY;
3396 *session_key = data_blob_dup_talloc(mem_ctx, sk);
3401 return NT_STATUS_OK;