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 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)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 (!NT_STATUS_IS_OK(status)) {
127 tevent_req_nterror(req, status);
131 state->num_read += received;
132 if (state->num_read == state->size) {
133 tevent_req_done(req);
137 subreq = state->transport->read_send(state, state->ev,
138 state->data + state->num_read,
139 state->size - state->num_read,
140 state->transport->priv);
141 if (tevent_req_nomem(subreq, req)) {
144 tevent_req_set_callback(subreq, rpc_read_done, req);
147 static NTSTATUS rpc_read_recv(struct tevent_req *req)
149 return tevent_req_simple_recv_ntstatus(req);
152 struct rpc_write_state {
153 struct tevent_context *ev;
154 struct rpc_cli_transport *transport;
160 static void rpc_write_done(struct tevent_req *subreq);
162 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
163 struct tevent_context *ev,
164 struct rpc_cli_transport *transport,
165 const uint8_t *data, size_t size)
167 struct tevent_req *req, *subreq;
168 struct rpc_write_state *state;
170 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
175 state->transport = transport;
178 state->num_written = 0;
180 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
182 subreq = transport->write_send(state, ev, data, size, transport->priv);
183 if (subreq == NULL) {
186 tevent_req_set_callback(subreq, rpc_write_done, req);
193 static void rpc_write_done(struct tevent_req *subreq)
195 struct tevent_req *req = tevent_req_callback_data(
196 subreq, struct tevent_req);
197 struct rpc_write_state *state = tevent_req_data(
198 req, struct rpc_write_state);
202 status = state->transport->write_recv(subreq, &written);
204 if (!NT_STATUS_IS_OK(status)) {
205 tevent_req_nterror(req, status);
209 state->num_written += written;
211 if (state->num_written == state->size) {
212 tevent_req_done(req);
216 subreq = state->transport->write_send(state, state->ev,
217 state->data + state->num_written,
218 state->size - state->num_written,
219 state->transport->priv);
220 if (tevent_req_nomem(subreq, req)) {
223 tevent_req_set_callback(subreq, rpc_write_done, req);
226 static NTSTATUS rpc_write_recv(struct tevent_req *req)
228 return tevent_req_simple_recv_ntstatus(req);
232 /****************************************************************************
233 Try and get a PDU's worth of data from current_pdu. If not, then read more
235 ****************************************************************************/
237 struct get_complete_frag_state {
238 struct tevent_context *ev;
239 struct rpc_pipe_client *cli;
244 static void get_complete_frag_got_header(struct tevent_req *subreq);
245 static void get_complete_frag_got_rest(struct tevent_req *subreq);
247 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
248 struct tevent_context *ev,
249 struct rpc_pipe_client *cli,
252 struct tevent_req *req, *subreq;
253 struct get_complete_frag_state *state;
257 req = tevent_req_create(mem_ctx, &state,
258 struct get_complete_frag_state);
264 state->frag_len = RPC_HEADER_LEN;
267 received = pdu->length;
268 if (received < RPC_HEADER_LEN) {
269 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
270 status = NT_STATUS_NO_MEMORY;
273 subreq = rpc_read_send(state, state->ev,
274 state->cli->transport,
275 pdu->data + received,
276 RPC_HEADER_LEN - received);
277 if (subreq == NULL) {
278 status = NT_STATUS_NO_MEMORY;
281 tevent_req_set_callback(subreq, get_complete_frag_got_header,
286 state->frag_len = dcerpc_get_frag_length(pdu);
287 if (state->frag_len < RPC_HEADER_LEN) {
288 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
289 return tevent_req_post(req, ev);
293 * Ensure we have frag_len bytes of data.
295 if (received < state->frag_len) {
296 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
297 status = NT_STATUS_NO_MEMORY;
300 subreq = rpc_read_send(state, state->ev,
301 state->cli->transport,
302 pdu->data + received,
303 state->frag_len - received);
304 if (subreq == NULL) {
305 status = NT_STATUS_NO_MEMORY;
308 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
313 status = NT_STATUS_OK;
315 if (NT_STATUS_IS_OK(status)) {
316 tevent_req_done(req);
318 tevent_req_nterror(req, status);
320 return tevent_req_post(req, ev);
323 static void get_complete_frag_got_header(struct tevent_req *subreq)
325 struct tevent_req *req = tevent_req_callback_data(
326 subreq, struct tevent_req);
327 struct get_complete_frag_state *state = tevent_req_data(
328 req, struct get_complete_frag_state);
331 status = rpc_read_recv(subreq);
333 if (!NT_STATUS_IS_OK(status)) {
334 tevent_req_nterror(req, status);
338 state->frag_len = dcerpc_get_frag_length(state->pdu);
339 if (state->frag_len < RPC_HEADER_LEN) {
340 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
344 if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
345 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
350 * We're here in this piece of code because we've read exactly
351 * RPC_HEADER_LEN bytes into state->pdu.
354 subreq = rpc_read_send(state, state->ev, state->cli->transport,
355 state->pdu->data + RPC_HEADER_LEN,
356 state->frag_len - RPC_HEADER_LEN);
357 if (tevent_req_nomem(subreq, req)) {
360 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
363 static void get_complete_frag_got_rest(struct tevent_req *subreq)
365 struct tevent_req *req = tevent_req_callback_data(
366 subreq, struct tevent_req);
369 status = rpc_read_recv(subreq);
371 if (!NT_STATUS_IS_OK(status)) {
372 tevent_req_nterror(req, status);
375 tevent_req_done(req);
378 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
380 return tevent_req_simple_recv_ntstatus(req);
383 /****************************************************************************
384 Do basic authentication checks on an incoming pdu.
385 ****************************************************************************/
387 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
388 struct rpc_pipe_client *cli,
389 struct ncacn_packet *pkt,
391 uint8_t expected_pkt_type,
394 DATA_BLOB *reply_pdu)
396 const struct dcerpc_response *r = NULL;
397 DATA_BLOB tmp_stub = data_blob_null;
401 * Point the return values at the real data including the RPC
402 * header. Just in case the caller wants it.
406 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
407 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
409 * TODO: do we still need this hack which was introduced
410 * in commit a42afcdcc7ab9aa9ed193ae36d3dbb10843447f0.
412 * I don't even know what AS/U might be...
414 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
415 "fragment first/last ON.\n"));
416 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
419 /* Ensure we have the correct type. */
420 switch (pkt->ptype) {
421 case DCERPC_PKT_BIND_NAK:
422 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
423 rpccli_pipe_txt(talloc_tos(), cli)));
425 ret = dcerpc_verify_ncacn_packet_header(pkt,
427 0, /* max_auth_info */
428 DCERPC_PFC_FLAG_FIRST |
429 DCERPC_PFC_FLAG_LAST,
430 0); /* optional flags */
431 if (!NT_STATUS_IS_OK(ret)) {
432 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
433 "RPC packet type - %u, expected %u: %s\n",
434 rpccli_pipe_txt(talloc_tos(), cli),
435 pkt->ptype, expected_pkt_type,
437 NDR_PRINT_DEBUG(ncacn_packet, pkt);
441 /* Use this for now... */
442 return NT_STATUS_NETWORK_ACCESS_DENIED;
444 case DCERPC_PKT_BIND_ACK:
445 ret = dcerpc_verify_ncacn_packet_header(pkt,
447 pkt->u.bind_ack.auth_info.length,
448 DCERPC_PFC_FLAG_FIRST |
449 DCERPC_PFC_FLAG_LAST,
450 DCERPC_PFC_FLAG_CONC_MPX |
451 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
452 if (!NT_STATUS_IS_OK(ret)) {
453 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
454 "RPC packet type - %u, expected %u: %s\n",
455 rpccli_pipe_txt(talloc_tos(), cli),
456 pkt->ptype, expected_pkt_type,
458 NDR_PRINT_DEBUG(ncacn_packet, pkt);
464 case DCERPC_PKT_ALTER_RESP:
465 ret = dcerpc_verify_ncacn_packet_header(pkt,
467 pkt->u.alter_resp.auth_info.length,
468 DCERPC_PFC_FLAG_FIRST |
469 DCERPC_PFC_FLAG_LAST,
470 DCERPC_PFC_FLAG_CONC_MPX |
471 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
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);
484 case DCERPC_PKT_RESPONSE:
486 r = &pkt->u.response;
488 ret = dcerpc_verify_ncacn_packet_header(pkt,
490 r->stub_and_verifier.length,
491 0, /* required_flags */
492 DCERPC_PFC_FLAG_FIRST |
493 DCERPC_PFC_FLAG_LAST);
494 if (!NT_STATUS_IS_OK(ret)) {
495 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
496 "RPC packet type - %u, expected %u: %s\n",
497 rpccli_pipe_txt(talloc_tos(), cli),
498 pkt->ptype, expected_pkt_type,
500 NDR_PRINT_DEBUG(ncacn_packet, pkt);
504 tmp_stub.data = r->stub_and_verifier.data;
505 tmp_stub.length = r->stub_and_verifier.length;
507 /* Here's where we deal with incoming sign/seal. */
508 ret = dcerpc_check_auth(cli->auth, pkt,
510 DCERPC_RESPONSE_LENGTH,
512 if (!NT_STATUS_IS_OK(ret)) {
513 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
514 "RPC packet type - %u, expected %u: %s\n",
515 rpccli_pipe_txt(talloc_tos(), cli),
516 pkt->ptype, expected_pkt_type,
518 NDR_PRINT_DEBUG(ncacn_packet, pkt);
522 /* Point the return values at the NDR data. */
525 DEBUG(10, ("Got pdu len %lu, data_len %lu\n",
526 (long unsigned int)pdu->length,
527 (long unsigned int)rdata->length));
530 * If this is the first reply, and the allocation hint is
531 * reasonable, try and set up the reply_pdu DATA_BLOB to the
535 if ((reply_pdu->length == 0) &&
536 r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
537 if (!data_blob_realloc(mem_ctx, reply_pdu,
539 DEBUG(0, ("reply alloc hint %d too "
540 "large to allocate\n",
541 (int)r->alloc_hint));
542 return NT_STATUS_NO_MEMORY;
548 case DCERPC_PKT_FAULT:
550 ret = dcerpc_verify_ncacn_packet_header(pkt,
552 0, /* max_auth_info */
553 DCERPC_PFC_FLAG_FIRST |
554 DCERPC_PFC_FLAG_LAST,
555 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
556 if (!NT_STATUS_IS_OK(ret)) {
557 DEBUG(1, (__location__ ": Connection to %s got an unexpected "
558 "RPC packet type - %u, expected %u: %s\n",
559 rpccli_pipe_txt(talloc_tos(), cli),
560 pkt->ptype, expected_pkt_type,
562 NDR_PRINT_DEBUG(ncacn_packet, pkt);
566 DEBUG(1, (__location__ ": RPC fault code %s received "
568 dcerpc_errstr(talloc_tos(),
569 pkt->u.fault.status),
570 rpccli_pipe_txt(talloc_tos(), cli)));
572 return dcerpc_fault_to_nt_status(pkt->u.fault.status);
575 DEBUG(0, (__location__ "Unknown packet type %u received "
577 (unsigned int)pkt->ptype,
578 rpccli_pipe_txt(talloc_tos(), cli)));
579 return NT_STATUS_RPC_PROTOCOL_ERROR;
583 if (pkt->call_id != call_id) {
584 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
585 "RPC call_id - %u, not %u\n",
586 rpccli_pipe_txt(talloc_tos(), cli),
587 pkt->call_id, call_id));
588 return NT_STATUS_RPC_PROTOCOL_ERROR;
594 /****************************************************************************
595 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
596 ****************************************************************************/
598 struct cli_api_pipe_state {
599 struct tevent_context *ev;
600 struct rpc_cli_transport *transport;
605 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
606 static void cli_api_pipe_write_done(struct tevent_req *subreq);
607 static void cli_api_pipe_read_done(struct tevent_req *subreq);
609 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
610 struct tevent_context *ev,
611 struct rpc_cli_transport *transport,
612 uint8_t *data, size_t data_len,
613 uint32_t max_rdata_len)
615 struct tevent_req *req, *subreq;
616 struct cli_api_pipe_state *state;
619 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
624 state->transport = transport;
626 if (max_rdata_len < RPC_HEADER_LEN) {
628 * For a RPC reply we always need at least RPC_HEADER_LEN
629 * bytes. We check this here because we will receive
630 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
632 status = NT_STATUS_INVALID_PARAMETER;
636 if (transport->trans_send != NULL) {
637 subreq = transport->trans_send(state, ev, data, data_len,
638 max_rdata_len, transport->priv);
639 if (subreq == NULL) {
642 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
647 * If the transport does not provide a "trans" routine, i.e. for
648 * example the ncacn_ip_tcp transport, do the write/read step here.
651 subreq = rpc_write_send(state, ev, transport, data, data_len);
652 if (subreq == NULL) {
655 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
659 tevent_req_nterror(req, status);
660 return tevent_req_post(req, ev);
666 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
668 struct tevent_req *req = tevent_req_callback_data(
669 subreq, struct tevent_req);
670 struct cli_api_pipe_state *state = tevent_req_data(
671 req, struct cli_api_pipe_state);
674 status = state->transport->trans_recv(subreq, state, &state->rdata,
677 if (!NT_STATUS_IS_OK(status)) {
678 tevent_req_nterror(req, status);
681 tevent_req_done(req);
684 static void cli_api_pipe_write_done(struct tevent_req *subreq)
686 struct tevent_req *req = tevent_req_callback_data(
687 subreq, struct tevent_req);
688 struct cli_api_pipe_state *state = tevent_req_data(
689 req, struct cli_api_pipe_state);
692 status = rpc_write_recv(subreq);
694 if (!NT_STATUS_IS_OK(status)) {
695 tevent_req_nterror(req, status);
699 state->rdata = talloc_array(state, uint8_t, RPC_HEADER_LEN);
700 if (tevent_req_nomem(state->rdata, req)) {
705 * We don't need to use rpc_read_send here, the upper layer will cope
706 * with a short read, transport->trans_send could also return less
707 * than state->max_rdata_len.
709 subreq = state->transport->read_send(state, state->ev, state->rdata,
711 state->transport->priv);
712 if (tevent_req_nomem(subreq, req)) {
715 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
718 static void cli_api_pipe_read_done(struct tevent_req *subreq)
720 struct tevent_req *req = tevent_req_callback_data(
721 subreq, struct tevent_req);
722 struct cli_api_pipe_state *state = tevent_req_data(
723 req, struct cli_api_pipe_state);
727 status = state->transport->read_recv(subreq, &received);
729 if (!NT_STATUS_IS_OK(status)) {
730 tevent_req_nterror(req, status);
733 state->rdata_len = received;
734 tevent_req_done(req);
737 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
738 uint8_t **prdata, uint32_t *prdata_len)
740 struct cli_api_pipe_state *state = tevent_req_data(
741 req, struct cli_api_pipe_state);
744 if (tevent_req_is_nterror(req, &status)) {
748 *prdata = talloc_move(mem_ctx, &state->rdata);
749 *prdata_len = state->rdata_len;
753 /****************************************************************************
754 Send data on an rpc pipe via trans. The data must be the last
755 pdu fragment of an NDR data stream.
757 Receive response data from an rpc pipe, which may be large...
759 Read the first fragment: unfortunately have to use SMBtrans for the first
760 bit, then SMBreadX for subsequent bits.
762 If first fragment received also wasn't the last fragment, continue
763 getting fragments until we _do_ receive the last fragment.
765 Request/Response PDU's look like the following...
767 |<------------------PDU len----------------------------------------------->|
768 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
770 +------------+-----------------+-------------+---------------+-------------+
771 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
772 +------------+-----------------+-------------+---------------+-------------+
774 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
775 signing & sealing being negotiated.
777 ****************************************************************************/
779 struct rpc_api_pipe_state {
780 struct tevent_context *ev;
781 struct rpc_pipe_client *cli;
782 uint8_t expected_pkt_type;
785 DATA_BLOB incoming_frag;
786 struct ncacn_packet *pkt;
790 size_t reply_pdu_offset;
794 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
795 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
796 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq);
798 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
799 struct tevent_context *ev,
800 struct rpc_pipe_client *cli,
801 DATA_BLOB *data, /* Outgoing PDU */
802 uint8_t expected_pkt_type,
805 struct tevent_req *req, *subreq;
806 struct rpc_api_pipe_state *state;
807 uint16_t max_recv_frag;
810 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
816 state->expected_pkt_type = expected_pkt_type;
817 state->call_id = call_id;
818 state->endianess = DCERPC_DREP_LE;
821 * Ensure we're not sending too much.
823 if (data->length > cli->max_xmit_frag) {
824 status = NT_STATUS_INVALID_PARAMETER;
828 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
830 if (state->expected_pkt_type == DCERPC_PKT_AUTH3) {
831 subreq = rpc_write_send(state, ev, cli->transport,
832 data->data, data->length);
833 if (subreq == NULL) {
836 tevent_req_set_callback(subreq, rpc_api_pipe_auth3_done, req);
840 /* get the header first, then fetch the rest once we have
841 * the frag_length available */
842 max_recv_frag = RPC_HEADER_LEN;
844 subreq = cli_api_pipe_send(state, ev, cli->transport,
845 data->data, data->length, max_recv_frag);
846 if (subreq == NULL) {
849 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
853 tevent_req_nterror(req, status);
854 return tevent_req_post(req, ev);
860 static void rpc_api_pipe_auth3_done(struct tevent_req *subreq)
862 struct tevent_req *req =
863 tevent_req_callback_data(subreq,
867 status = rpc_write_recv(subreq);
869 if (!NT_STATUS_IS_OK(status)) {
870 tevent_req_nterror(req, status);
874 tevent_req_done(req);
877 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
879 struct tevent_req *req = tevent_req_callback_data(
880 subreq, struct tevent_req);
881 struct rpc_api_pipe_state *state = tevent_req_data(
882 req, struct rpc_api_pipe_state);
884 uint8_t *rdata = NULL;
885 uint32_t rdata_len = 0;
887 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
889 if (!NT_STATUS_IS_OK(status)) {
890 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
891 tevent_req_nterror(req, status);
896 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
897 rpccli_pipe_txt(talloc_tos(), state->cli)));
898 tevent_req_done(req);
903 * Move data on state->incoming_frag.
905 state->incoming_frag.data = talloc_move(state, &rdata);
906 state->incoming_frag.length = rdata_len;
907 if (!state->incoming_frag.data) {
908 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
912 /* Ensure we have enough data for a pdu. */
913 subreq = get_complete_frag_send(state, state->ev, state->cli,
914 &state->incoming_frag);
915 if (tevent_req_nomem(subreq, req)) {
918 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
921 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
923 struct tevent_req *req = tevent_req_callback_data(
924 subreq, struct tevent_req);
925 struct rpc_api_pipe_state *state = tevent_req_data(
926 req, struct rpc_api_pipe_state);
928 DATA_BLOB rdata = data_blob_null;
930 status = get_complete_frag_recv(subreq);
932 if (!NT_STATUS_IS_OK(status)) {
933 DEBUG(5, ("get_complete_frag failed: %s\n",
935 tevent_req_nterror(req, status);
939 state->pkt = talloc(state, struct ncacn_packet);
942 * TODO: do a real async disconnect ...
944 * For now do it sync...
946 TALLOC_FREE(state->cli->transport);
947 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
951 status = dcerpc_pull_ncacn_packet(state->pkt,
952 &state->incoming_frag,
954 if (!NT_STATUS_IS_OK(status)) {
956 * TODO: do a real async disconnect ...
958 * For now do it sync...
960 TALLOC_FREE(state->cli->transport);
961 tevent_req_nterror(req, status);
965 if (DEBUGLEVEL >= 10) {
966 NDR_PRINT_DEBUG(ncacn_packet, state->pkt);
969 status = cli_pipe_validate_current_pdu(state,
970 state->cli, state->pkt,
971 &state->incoming_frag,
972 state->expected_pkt_type,
977 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
978 (unsigned)state->incoming_frag.length,
979 (unsigned)state->reply_pdu_offset,
982 if (state->pkt->ptype != DCERPC_PKT_FAULT && !NT_STATUS_IS_OK(status)) {
984 * TODO: do a real async disconnect ...
986 * For now do it sync...
988 TALLOC_FREE(state->cli->transport);
989 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
991 * TODO: do a real async disconnect ...
993 * For now do it sync...
995 TALLOC_FREE(state->cli->transport);
996 } else if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
998 * TODO: do a real async disconnect ...
1000 * For now do it sync...
1002 TALLOC_FREE(state->cli->transport);
1004 if (!NT_STATUS_IS_OK(status)) {
1005 tevent_req_nterror(req, status);
1009 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
1010 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
1012 * Set the data type correctly for big-endian data on the
1015 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
1017 rpccli_pipe_txt(talloc_tos(), state->cli)));
1018 state->endianess = 0x00; /* BIG ENDIAN */
1021 * Check endianness on subsequent packets.
1023 if (state->endianess != state->pkt->drep[0]) {
1024 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
1026 state->endianess?"little":"big",
1027 state->pkt->drep[0]?"little":"big"));
1029 * TODO: do a real async disconnect ...
1031 * For now do it sync...
1033 TALLOC_FREE(state->cli->transport);
1034 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1038 if (state->reply_pdu_offset + rdata.length > MAX_RPC_DATA_SIZE) {
1040 * TODO: do a real async disconnect ...
1042 * For now do it sync...
1044 TALLOC_FREE(state->cli->transport);
1045 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1049 /* Now copy the data portion out of the pdu into rbuf. */
1050 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
1051 if (!data_blob_realloc(NULL, &state->reply_pdu,
1052 state->reply_pdu_offset + rdata.length)) {
1054 * TODO: do a real async disconnect ...
1056 * For now do it sync...
1058 TALLOC_FREE(state->cli->transport);
1059 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1064 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
1065 rdata.data, rdata.length);
1066 state->reply_pdu_offset += rdata.length;
1068 /* reset state->incoming_frag, there is no need to free it,
1069 * it will be reallocated to the right size the next time
1071 state->incoming_frag.length = 0;
1073 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1074 /* make sure the pdu length is right now that we
1075 * have all the data available (alloc hint may
1076 * have allocated more than was actually used) */
1077 state->reply_pdu.length = state->reply_pdu_offset;
1078 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
1079 rpccli_pipe_txt(talloc_tos(), state->cli),
1080 (unsigned)state->reply_pdu.length));
1081 tevent_req_done(req);
1085 subreq = get_complete_frag_send(state, state->ev, state->cli,
1086 &state->incoming_frag);
1087 if (subreq == NULL) {
1089 * TODO: do a real async disconnect ...
1091 * For now do it sync...
1093 TALLOC_FREE(state->cli->transport);
1095 if (tevent_req_nomem(subreq, req)) {
1098 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
1101 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1102 struct ncacn_packet **pkt,
1103 DATA_BLOB *reply_pdu)
1105 struct rpc_api_pipe_state *state = tevent_req_data(
1106 req, struct rpc_api_pipe_state);
1109 if (tevent_req_is_nterror(req, &status)) {
1113 /* return data to caller and assign it ownership of memory */
1115 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1116 reply_pdu->length = state->reply_pdu.length;
1117 state->reply_pdu.length = 0;
1119 data_blob_free(&state->reply_pdu);
1123 *pkt = talloc_steal(mem_ctx, state->pkt);
1126 return NT_STATUS_OK;
1129 /*******************************************************************
1130 Creates NTLMSSP auth bind.
1131 ********************************************************************/
1133 static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1134 TALLOC_CTX *mem_ctx,
1135 DATA_BLOB *auth_token,
1136 bool *client_hdr_signing)
1138 struct gensec_security *gensec_security;
1139 DATA_BLOB null_blob = data_blob_null;
1142 gensec_security = cli->auth->auth_ctx;
1144 DEBUG(5, ("create_generic_auth_rpc_bind_req: generate first token\n"));
1145 status = gensec_update(gensec_security, mem_ctx, null_blob, auth_token);
1147 if (!NT_STATUS_IS_OK(status) &&
1148 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
1153 if (client_hdr_signing == NULL) {
1157 if (cli->auth->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1158 *client_hdr_signing = false;
1162 *client_hdr_signing = gensec_have_feature(gensec_security,
1163 GENSEC_FEATURE_SIGN_PKT_HEADER);
1168 /*******************************************************************
1169 Creates the internals of a DCE/RPC bind request or alter context PDU.
1170 ********************************************************************/
1172 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1173 enum dcerpc_pkt_type ptype,
1174 uint32_t rpc_call_id,
1175 const struct ndr_syntax_id *abstract,
1176 const struct ndr_syntax_id *transfer,
1177 const DATA_BLOB *auth_info,
1178 bool client_hdr_signing,
1181 uint16_t auth_len = auth_info->length;
1183 union dcerpc_payload u;
1184 struct dcerpc_ctx_list ctx_list;
1185 uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1188 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1191 if (client_hdr_signing) {
1192 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1195 ctx_list.context_id = 0;
1196 ctx_list.num_transfer_syntaxes = 1;
1197 ctx_list.abstract_syntax = *abstract;
1198 ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1200 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1201 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1202 u.bind.assoc_group_id = 0x0;
1203 u.bind.num_contexts = 1;
1204 u.bind.ctx_list = &ctx_list;
1205 u.bind.auth_info = *auth_info;
1207 status = dcerpc_push_ncacn_packet(mem_ctx,
1213 if (!NT_STATUS_IS_OK(status)) {
1214 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1218 return NT_STATUS_OK;
1221 /*******************************************************************
1222 Creates a DCE/RPC bind request.
1223 ********************************************************************/
1225 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1226 struct rpc_pipe_client *cli,
1227 struct pipe_auth_data *auth,
1228 uint32_t rpc_call_id,
1229 const struct ndr_syntax_id *abstract,
1230 const struct ndr_syntax_id *transfer,
1233 DATA_BLOB auth_token = data_blob_null;
1234 DATA_BLOB auth_info = data_blob_null;
1237 switch (auth->auth_type) {
1238 case DCERPC_AUTH_TYPE_NONE:
1242 ret = create_generic_auth_rpc_bind_req(cli, mem_ctx,
1244 &auth->client_hdr_signing);
1246 if (!NT_STATUS_IS_OK(ret) &&
1247 !NT_STATUS_EQUAL(ret, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1253 if (auth_token.length != 0) {
1254 ret = dcerpc_push_dcerpc_auth(cli,
1257 0, /* auth_pad_length */
1258 auth->auth_context_id,
1261 if (!NT_STATUS_IS_OK(ret)) {
1264 data_blob_free(&auth_token);
1267 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1273 auth->client_hdr_signing,
1278 /*******************************************************************
1280 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1281 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1282 and deals with signing/sealing details.
1283 ********************************************************************/
1285 struct rpc_api_pipe_req_state {
1286 struct tevent_context *ev;
1287 struct rpc_pipe_client *cli;
1290 const DATA_BLOB *req_data;
1291 const struct GUID *object_uuid;
1292 uint32_t req_data_sent;
1293 DATA_BLOB req_trailer;
1294 uint32_t req_trailer_sent;
1295 bool verify_bitmask1;
1296 bool verify_pcontext;
1298 DATA_BLOB reply_pdu;
1301 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1302 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1303 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state);
1304 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1305 bool *is_last_frag);
1307 static struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1308 struct tevent_context *ev,
1309 struct rpc_pipe_client *cli,
1311 const struct GUID *object_uuid,
1312 const DATA_BLOB *req_data)
1314 struct tevent_req *req, *subreq;
1315 struct rpc_api_pipe_req_state *state;
1319 req = tevent_req_create(mem_ctx, &state,
1320 struct rpc_api_pipe_req_state);
1326 state->op_num = op_num;
1327 state->object_uuid = object_uuid;
1328 state->req_data = req_data;
1329 state->req_data_sent = 0;
1330 state->call_id = get_rpc_call_id();
1331 state->reply_pdu = data_blob_null;
1332 state->rpc_out = data_blob_null;
1334 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1335 + RPC_MAX_SIGN_SIZE) {
1336 /* Server is screwed up ! */
1337 status = NT_STATUS_INVALID_PARAMETER;
1341 status = prepare_verification_trailer(state);
1342 if (!NT_STATUS_IS_OK(status)) {
1346 status = prepare_next_frag(state, &is_last_frag);
1347 if (!NT_STATUS_IS_OK(status)) {
1352 subreq = rpc_api_pipe_send(state, ev, state->cli,
1354 DCERPC_PKT_RESPONSE,
1356 if (subreq == NULL) {
1359 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1361 subreq = rpc_write_send(state, ev, cli->transport,
1362 state->rpc_out.data,
1363 state->rpc_out.length);
1364 if (subreq == NULL) {
1367 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1373 tevent_req_nterror(req, status);
1374 return tevent_req_post(req, ev);
1380 static NTSTATUS prepare_verification_trailer(struct rpc_api_pipe_req_state *state)
1382 struct pipe_auth_data *a = state->cli->auth;
1383 struct dcerpc_sec_verification_trailer *t;
1384 struct dcerpc_sec_vt *c = NULL;
1385 struct ndr_push *ndr = NULL;
1386 enum ndr_err_code ndr_err;
1391 return NT_STATUS_OK;
1394 if (a->auth_level < DCERPC_AUTH_LEVEL_PACKET) {
1395 return NT_STATUS_OK;
1398 t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1400 return NT_STATUS_NO_MEMORY;
1403 if (!a->verified_bitmask1) {
1404 t->commands = talloc_realloc(t, t->commands,
1405 struct dcerpc_sec_vt,
1406 t->count.count + 1);
1407 if (t->commands == NULL) {
1408 return NT_STATUS_NO_MEMORY;
1410 c = &t->commands[t->count.count++];
1413 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1414 if (a->client_hdr_signing) {
1415 c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1417 state->verify_bitmask1 = true;
1420 if (!state->cli->verified_pcontext) {
1421 t->commands = talloc_realloc(t, t->commands,
1422 struct dcerpc_sec_vt,
1423 t->count.count + 1);
1424 if (t->commands == NULL) {
1425 return NT_STATUS_NO_MEMORY;
1427 c = &t->commands[t->count.count++];
1430 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1431 c->u.pcontext.abstract_syntax = state->cli->abstract_syntax;
1432 c->u.pcontext.transfer_syntax = state->cli->transfer_syntax;
1434 state->verify_pcontext = true;
1437 if (!a->hdr_signing) {
1438 t->commands = talloc_realloc(t, t->commands,
1439 struct dcerpc_sec_vt,
1440 t->count.count + 1);
1441 if (t->commands == NULL) {
1442 return NT_STATUS_NO_MEMORY;
1444 c = &t->commands[t->count.count++];
1447 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1448 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1449 c->u.header2.drep[0] = DCERPC_DREP_LE;
1450 c->u.header2.drep[1] = 0;
1451 c->u.header2.drep[2] = 0;
1452 c->u.header2.drep[3] = 0;
1453 c->u.header2.call_id = state->call_id;
1454 c->u.header2.context_id = 0;
1455 c->u.header2.opnum = state->op_num;
1458 if (t->count.count == 0) {
1460 return NT_STATUS_OK;
1463 c = &t->commands[t->count.count - 1];
1464 c->command |= DCERPC_SEC_VT_COMMAND_END;
1466 if (DEBUGLEVEL >= 10) {
1467 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1470 ndr = ndr_push_init_ctx(state);
1472 return NT_STATUS_NO_MEMORY;
1475 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1476 NDR_SCALARS | NDR_BUFFERS,
1478 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1479 return ndr_map_error2ntstatus(ndr_err);
1481 state->req_trailer = ndr_push_blob(ndr);
1483 align = state->req_data->length & 0x3;
1490 const uint8_t zeros[4] = { 0, };
1492 ok = data_blob_append(ndr, &state->req_trailer, zeros, pad);
1494 return NT_STATUS_NO_MEMORY;
1497 /* move the padding to the start */
1498 p = state->req_trailer.data;
1499 memmove(p + pad, p, state->req_trailer.length - pad);
1503 return NT_STATUS_OK;
1506 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1514 size_t data_thistime;
1515 size_t trailer_left;
1516 size_t trailer_thistime = 0;
1518 size_t total_thistime;
1521 union dcerpc_payload u;
1523 data_left = state->req_data->length - state->req_data_sent;
1524 trailer_left = state->req_trailer.length - state->req_trailer_sent;
1525 total_left = data_left + trailer_left;
1526 if ((total_left < data_left) || (total_left < trailer_left)) {
1530 return NT_STATUS_INVALID_PARAMETER_MIX;
1533 status = dcerpc_guess_sizes(state->cli->auth,
1534 DCERPC_REQUEST_LENGTH, total_left,
1535 state->cli->max_xmit_frag,
1537 &frag_len, &auth_len, &pad_len);
1538 if (!NT_STATUS_IS_OK(status)) {
1542 if (state->req_data_sent == 0) {
1543 flags = DCERPC_PFC_FLAG_FIRST;
1546 if (total_thistime == total_left) {
1547 flags |= DCERPC_PFC_FLAG_LAST;
1550 data_thistime = MIN(total_thistime, data_left);
1551 if (data_thistime < total_thistime) {
1552 trailer_thistime = total_thistime - data_thistime;
1555 data_blob_free(&state->rpc_out);
1557 ZERO_STRUCT(u.request);
1559 u.request.alloc_hint = total_left;
1560 u.request.context_id = 0;
1561 u.request.opnum = state->op_num;
1563 if (state->object_uuid) {
1564 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1565 u.request.object.object = *state->object_uuid;
1566 frag_len += ndr_size_GUID(state->object_uuid, 0);
1569 status = dcerpc_push_ncacn_packet(state,
1576 if (!NT_STATUS_IS_OK(status)) {
1580 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1581 * compute it right for requests because the auth trailer is missing
1583 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1585 if (data_thistime > 0) {
1586 /* Copy in the data. */
1587 ok = data_blob_append(NULL, &state->rpc_out,
1588 state->req_data->data + state->req_data_sent,
1591 return NT_STATUS_NO_MEMORY;
1593 state->req_data_sent += data_thistime;
1596 if (trailer_thistime > 0) {
1597 /* Copy in the verification trailer. */
1598 ok = data_blob_append(NULL, &state->rpc_out,
1599 state->req_trailer.data + state->req_trailer_sent,
1602 return NT_STATUS_NO_MEMORY;
1604 state->req_trailer_sent += trailer_thistime;
1607 switch (state->cli->auth->auth_level) {
1608 case DCERPC_AUTH_LEVEL_NONE:
1609 case DCERPC_AUTH_LEVEL_CONNECT:
1611 case DCERPC_AUTH_LEVEL_PACKET:
1612 case DCERPC_AUTH_LEVEL_INTEGRITY:
1613 case DCERPC_AUTH_LEVEL_PRIVACY:
1614 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1616 if (!NT_STATUS_IS_OK(status)) {
1621 return NT_STATUS_INVALID_PARAMETER;
1624 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1629 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1631 struct tevent_req *req = tevent_req_callback_data(
1632 subreq, struct tevent_req);
1633 struct rpc_api_pipe_req_state *state = tevent_req_data(
1634 req, struct rpc_api_pipe_req_state);
1638 status = rpc_write_recv(subreq);
1639 TALLOC_FREE(subreq);
1640 if (!NT_STATUS_IS_OK(status)) {
1641 tevent_req_nterror(req, status);
1645 status = prepare_next_frag(state, &is_last_frag);
1646 if (!NT_STATUS_IS_OK(status)) {
1647 tevent_req_nterror(req, status);
1652 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1654 DCERPC_PKT_RESPONSE,
1656 if (tevent_req_nomem(subreq, req)) {
1659 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1661 subreq = rpc_write_send(state, state->ev,
1662 state->cli->transport,
1663 state->rpc_out.data,
1664 state->rpc_out.length);
1665 if (tevent_req_nomem(subreq, req)) {
1668 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1673 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1675 struct tevent_req *req = tevent_req_callback_data(
1676 subreq, struct tevent_req);
1677 struct rpc_api_pipe_req_state *state = tevent_req_data(
1678 req, struct rpc_api_pipe_req_state);
1681 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1682 TALLOC_FREE(subreq);
1683 if (!NT_STATUS_IS_OK(status)) {
1684 tevent_req_nterror(req, status);
1688 if (state->cli->auth == NULL) {
1689 tevent_req_done(req);
1693 if (state->verify_bitmask1) {
1694 state->cli->auth->verified_bitmask1 = true;
1697 if (state->verify_pcontext) {
1698 state->cli->verified_pcontext = true;
1701 tevent_req_done(req);
1704 static NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1705 DATA_BLOB *reply_pdu)
1707 struct rpc_api_pipe_req_state *state = tevent_req_data(
1708 req, struct rpc_api_pipe_req_state);
1711 if (tevent_req_is_nterror(req, &status)) {
1713 * We always have to initialize to reply pdu, even if there is
1714 * none. The rpccli_* caller routines expect this.
1716 *reply_pdu = data_blob_null;
1720 /* return data to caller and assign it ownership of memory */
1721 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1722 reply_pdu->length = state->reply_pdu.length;
1723 state->reply_pdu.length = 0;
1725 return NT_STATUS_OK;
1728 /****************************************************************************
1729 Check the rpc bind acknowledge response.
1730 ****************************************************************************/
1732 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1733 const struct ndr_syntax_id *transfer)
1735 struct dcerpc_ack_ctx ctx;
1737 if (r->secondary_address_size == 0) {
1738 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1741 if (r->num_results < 1 || !r->ctx_list) {
1745 ctx = r->ctx_list[0];
1747 /* check the transfer syntax */
1748 if ((ctx.syntax.if_version != transfer->if_version) ||
1749 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1750 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1754 if (r->num_results != 0x1 || ctx.result != 0) {
1755 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1756 r->num_results, ctx.reason.value));
1759 DEBUG(5,("check_bind_response: accepted!\n"));
1763 /*******************************************************************
1764 Creates a DCE/RPC bind authentication response.
1765 This is the packet that is sent back to the server once we
1766 have received a BIND-ACK, to finish the third leg of
1767 the authentication handshake.
1768 ********************************************************************/
1770 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1771 struct rpc_pipe_client *cli,
1772 struct pipe_auth_data *auth,
1773 uint32_t rpc_call_id,
1774 DATA_BLOB *pauth_blob,
1778 union dcerpc_payload u;
1782 status = dcerpc_push_dcerpc_auth(mem_ctx,
1785 0, /* auth_pad_length */
1786 auth->auth_context_id,
1788 &u.auth3.auth_info);
1789 if (!NT_STATUS_IS_OK(status)) {
1793 status = dcerpc_push_ncacn_packet(mem_ctx,
1795 DCERPC_PFC_FLAG_FIRST |
1796 DCERPC_PFC_FLAG_LAST,
1801 data_blob_free(&u.auth3.auth_info);
1802 if (!NT_STATUS_IS_OK(status)) {
1803 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1807 return NT_STATUS_OK;
1810 /*******************************************************************
1811 Creates a DCE/RPC bind alter context authentication request which
1812 may contain a spnego auth blob
1813 ********************************************************************/
1815 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1816 struct pipe_auth_data *auth,
1817 uint32_t rpc_call_id,
1818 const struct ndr_syntax_id *abstract,
1819 const struct ndr_syntax_id *transfer,
1820 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1823 DATA_BLOB auth_info;
1826 status = dcerpc_push_dcerpc_auth(mem_ctx,
1829 0, /* auth_pad_length */
1830 auth->auth_context_id,
1833 if (!NT_STATUS_IS_OK(status)) {
1837 status = create_bind_or_alt_ctx_internal(mem_ctx,
1843 false, /* client_hdr_signing */
1845 data_blob_free(&auth_info);
1849 /****************************************************************************
1851 ****************************************************************************/
1853 struct rpc_pipe_bind_state {
1854 struct tevent_context *ev;
1855 struct rpc_pipe_client *cli;
1858 uint32_t rpc_call_id;
1861 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1862 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1863 struct rpc_pipe_bind_state *state,
1864 DATA_BLOB *credentials);
1865 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1866 struct rpc_pipe_bind_state *state,
1867 DATA_BLOB *credentials);
1869 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1870 struct tevent_context *ev,
1871 struct rpc_pipe_client *cli,
1872 struct pipe_auth_data *auth)
1874 struct tevent_req *req, *subreq;
1875 struct rpc_pipe_bind_state *state;
1878 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1883 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1884 rpccli_pipe_txt(talloc_tos(), cli),
1885 (unsigned int)auth->auth_type,
1886 (unsigned int)auth->auth_level ));
1890 state->rpc_call_id = get_rpc_call_id();
1892 cli->auth = talloc_move(cli, &auth);
1894 /* Marshall the outgoing data. */
1895 status = create_rpc_bind_req(state, cli,
1898 &cli->abstract_syntax,
1899 &cli->transfer_syntax,
1902 if (!NT_STATUS_IS_OK(status) &&
1903 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1907 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1908 DCERPC_PKT_BIND_ACK, state->rpc_call_id);
1909 if (subreq == NULL) {
1912 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1916 tevent_req_nterror(req, status);
1917 return tevent_req_post(req, ev);
1923 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1925 struct tevent_req *req = tevent_req_callback_data(
1926 subreq, struct tevent_req);
1927 struct rpc_pipe_bind_state *state = tevent_req_data(
1928 req, struct rpc_pipe_bind_state);
1929 struct pipe_auth_data *pauth = state->cli->auth;
1930 struct gensec_security *gensec_security;
1931 struct ncacn_packet *pkt = NULL;
1932 struct dcerpc_auth auth;
1933 DATA_BLOB auth_token = data_blob_null;
1936 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, NULL);
1937 TALLOC_FREE(subreq);
1938 if (!NT_STATUS_IS_OK(status)) {
1939 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1940 rpccli_pipe_txt(talloc_tos(), state->cli),
1941 nt_errstr(status)));
1942 tevent_req_nterror(req, status);
1947 tevent_req_done(req);
1951 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1952 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1953 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1957 if (pkt->ptype == DCERPC_PKT_BIND_ACK) {
1958 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1959 if (pauth->client_hdr_signing) {
1960 pauth->hdr_signing = true;
1965 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1967 switch(pauth->auth_type) {
1969 case DCERPC_AUTH_TYPE_NONE:
1970 /* Bind complete. */
1971 tevent_req_done(req);
1975 if (pkt->auth_length == 0) {
1976 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1980 /* get auth credentials */
1981 status = dcerpc_pull_auth_trailer(pkt, talloc_tos(),
1982 &pkt->u.bind_ack.auth_info,
1984 if (!NT_STATUS_IS_OK(status)) {
1985 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1986 nt_errstr(status)));
1987 tevent_req_nterror(req, status);
1991 if (auth.auth_type != pauth->auth_type) {
1992 DEBUG(0, (__location__ " Auth type %u mismatch expected %u.\n",
1993 auth.auth_type, pauth->auth_type));
1994 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
1998 if (auth.auth_level != pauth->auth_level) {
1999 DEBUG(0, (__location__ " Auth level %u mismatch expected %u.\n",
2000 auth.auth_level, pauth->auth_level));
2001 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
2005 if (auth.auth_context_id != pauth->auth_context_id) {
2006 DEBUG(0, (__location__ " Auth context id %u mismatch expected %u.\n",
2007 (unsigned)auth.auth_context_id,
2008 (unsigned)pauth->auth_context_id));
2009 tevent_req_nterror(req, NT_STATUS_RPC_PROTOCOL_ERROR);
2017 * For authenticated binds we may need to do 3 or 4 leg binds.
2020 switch(pauth->auth_type) {
2022 case DCERPC_AUTH_TYPE_NONE:
2023 /* Bind complete. */
2024 tevent_req_done(req);
2028 gensec_security = pauth->auth_ctx;
2031 status = gensec_update(gensec_security, state,
2032 auth.credentials, &auth_token);
2033 if (NT_STATUS_EQUAL(status,
2034 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2035 status = rpc_bind_next_send(req, state,
2037 } else if (NT_STATUS_IS_OK(status)) {
2038 if (pauth->hdr_signing) {
2039 gensec_want_feature(gensec_security,
2040 GENSEC_FEATURE_SIGN_PKT_HEADER);
2043 if (auth_token.length == 0) {
2044 /* Bind complete. */
2045 tevent_req_done(req);
2048 status = rpc_bind_finish_send(req, state,
2054 if (!NT_STATUS_IS_OK(status)) {
2055 tevent_req_nterror(req, status);
2060 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
2061 struct rpc_pipe_bind_state *state,
2062 DATA_BLOB *auth_token)
2064 struct pipe_auth_data *auth = state->cli->auth;
2065 struct tevent_req *subreq;
2068 /* Now prepare the alter context pdu. */
2069 data_blob_free(&state->rpc_out);
2071 status = create_rpc_alter_context(state, auth,
2073 &state->cli->abstract_syntax,
2074 &state->cli->transfer_syntax,
2077 if (!NT_STATUS_IS_OK(status)) {
2081 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2082 &state->rpc_out, DCERPC_PKT_ALTER_RESP,
2083 state->rpc_call_id);
2084 if (subreq == NULL) {
2085 return NT_STATUS_NO_MEMORY;
2087 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2088 return NT_STATUS_OK;
2091 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
2092 struct rpc_pipe_bind_state *state,
2093 DATA_BLOB *auth_token)
2095 struct pipe_auth_data *auth = state->cli->auth;
2096 struct tevent_req *subreq;
2099 state->auth3 = true;
2101 /* Now prepare the auth3 context pdu. */
2102 data_blob_free(&state->rpc_out);
2104 status = create_rpc_bind_auth3(state, state->cli, auth,
2108 if (!NT_STATUS_IS_OK(status)) {
2112 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
2113 &state->rpc_out, DCERPC_PKT_AUTH3,
2114 state->rpc_call_id);
2115 if (subreq == NULL) {
2116 return NT_STATUS_NO_MEMORY;
2118 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
2119 return NT_STATUS_OK;
2122 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
2124 return tevent_req_simple_recv_ntstatus(req);
2127 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
2128 struct pipe_auth_data *auth)
2130 TALLOC_CTX *frame = talloc_stackframe();
2131 struct tevent_context *ev;
2132 struct tevent_req *req;
2133 NTSTATUS status = NT_STATUS_OK;
2135 ev = samba_tevent_context_init(frame);
2137 status = NT_STATUS_NO_MEMORY;
2141 req = rpc_pipe_bind_send(frame, ev, cli, auth);
2143 status = NT_STATUS_NO_MEMORY;
2147 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2151 status = rpc_pipe_bind_recv(req);
2157 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
2159 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
2160 unsigned int timeout)
2162 if (rpc_cli == NULL) {
2163 return RPCCLI_DEFAULT_TIMEOUT;
2166 if (rpc_cli->binding_handle == NULL) {
2167 return RPCCLI_DEFAULT_TIMEOUT;
2170 return dcerpc_binding_handle_set_timeout(rpc_cli->binding_handle,
2174 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2176 if (rpc_cli == NULL) {
2180 if (rpc_cli->binding_handle == NULL) {
2184 return dcerpc_binding_handle_is_connected(rpc_cli->binding_handle);
2187 struct rpccli_bh_state {
2188 struct rpc_pipe_client *rpc_cli;
2191 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2193 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2194 struct rpccli_bh_state);
2195 struct rpc_cli_transport *transport = hs->rpc_cli->transport;
2197 if (transport == NULL) {
2201 if (transport->is_connected == NULL) {
2205 return transport->is_connected(transport->priv);
2208 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2211 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2212 struct rpccli_bh_state);
2213 struct rpc_cli_transport *transport = hs->rpc_cli->transport;
2216 if (transport == NULL) {
2217 return RPCCLI_DEFAULT_TIMEOUT;
2220 if (transport->set_timeout == NULL) {
2221 return RPCCLI_DEFAULT_TIMEOUT;
2224 old = transport->set_timeout(transport->priv, timeout);
2226 return RPCCLI_DEFAULT_TIMEOUT;
2232 static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
2233 enum dcerpc_AuthType *auth_type,
2234 enum dcerpc_AuthLevel *auth_level)
2236 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2237 struct rpccli_bh_state);
2239 if (hs->rpc_cli == NULL) {
2243 if (hs->rpc_cli->auth == NULL) {
2247 *auth_type = hs->rpc_cli->auth->auth_type;
2248 *auth_level = hs->rpc_cli->auth->auth_level;
2251 struct rpccli_bh_raw_call_state {
2257 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2259 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2260 struct tevent_context *ev,
2261 struct dcerpc_binding_handle *h,
2262 const struct GUID *object,
2265 const uint8_t *in_data,
2268 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2269 struct rpccli_bh_state);
2270 struct tevent_req *req;
2271 struct rpccli_bh_raw_call_state *state;
2273 struct tevent_req *subreq;
2275 req = tevent_req_create(mem_ctx, &state,
2276 struct rpccli_bh_raw_call_state);
2280 state->in_data.data = discard_const_p(uint8_t, in_data);
2281 state->in_data.length = in_length;
2283 ok = rpccli_bh_is_connected(h);
2285 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2286 return tevent_req_post(req, ev);
2289 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2290 opnum, object, &state->in_data);
2291 if (tevent_req_nomem(subreq, req)) {
2292 return tevent_req_post(req, ev);
2294 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2299 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2301 struct tevent_req *req =
2302 tevent_req_callback_data(subreq,
2304 struct rpccli_bh_raw_call_state *state =
2305 tevent_req_data(req,
2306 struct rpccli_bh_raw_call_state);
2309 state->out_flags = 0;
2311 /* TODO: support bigendian responses */
2313 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2314 TALLOC_FREE(subreq);
2315 if (!NT_STATUS_IS_OK(status)) {
2316 tevent_req_nterror(req, status);
2320 tevent_req_done(req);
2323 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2324 TALLOC_CTX *mem_ctx,
2327 uint32_t *out_flags)
2329 struct rpccli_bh_raw_call_state *state =
2330 tevent_req_data(req,
2331 struct rpccli_bh_raw_call_state);
2334 if (tevent_req_is_nterror(req, &status)) {
2335 tevent_req_received(req);
2339 *out_data = talloc_move(mem_ctx, &state->out_data.data);
2340 *out_length = state->out_data.length;
2341 *out_flags = state->out_flags;
2342 tevent_req_received(req);
2343 return NT_STATUS_OK;
2346 struct rpccli_bh_disconnect_state {
2350 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2351 struct tevent_context *ev,
2352 struct dcerpc_binding_handle *h)
2354 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2355 struct rpccli_bh_state);
2356 struct tevent_req *req;
2357 struct rpccli_bh_disconnect_state *state;
2360 req = tevent_req_create(mem_ctx, &state,
2361 struct rpccli_bh_disconnect_state);
2366 ok = rpccli_bh_is_connected(h);
2368 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2369 return tevent_req_post(req, ev);
2373 * TODO: do a real async disconnect ...
2375 * For now we do it sync...
2377 TALLOC_FREE(hs->rpc_cli->transport);
2380 tevent_req_done(req);
2381 return tevent_req_post(req, ev);
2384 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2388 if (tevent_req_is_nterror(req, &status)) {
2389 tevent_req_received(req);
2393 tevent_req_received(req);
2394 return NT_STATUS_OK;
2397 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2402 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2404 const void *_struct_ptr,
2405 const struct ndr_interface_call *call)
2407 void *struct_ptr = discard_const(_struct_ptr);
2409 if (DEBUGLEVEL < 10) {
2413 if (ndr_flags & NDR_IN) {
2414 ndr_print_function_debug(call->ndr_print,
2419 if (ndr_flags & NDR_OUT) {
2420 ndr_print_function_debug(call->ndr_print,
2427 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2429 .is_connected = rpccli_bh_is_connected,
2430 .set_timeout = rpccli_bh_set_timeout,
2431 .auth_info = rpccli_bh_auth_info,
2432 .raw_call_send = rpccli_bh_raw_call_send,
2433 .raw_call_recv = rpccli_bh_raw_call_recv,
2434 .disconnect_send = rpccli_bh_disconnect_send,
2435 .disconnect_recv = rpccli_bh_disconnect_recv,
2437 .ref_alloc = rpccli_bh_ref_alloc,
2438 .do_ndr_print = rpccli_bh_do_ndr_print,
2441 /* initialise a rpc_pipe_client binding handle */
2442 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2443 const struct GUID *object,
2444 const struct ndr_interface_table *table)
2446 struct dcerpc_binding_handle *h;
2447 struct rpccli_bh_state *hs;
2449 h = dcerpc_binding_handle_create(c,
2454 struct rpccli_bh_state,
2464 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2465 struct pipe_auth_data **presult)
2467 struct pipe_auth_data *result;
2468 struct auth_generic_state *auth_generic_ctx;
2471 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2472 if (result == NULL) {
2473 return NT_STATUS_NO_MEMORY;
2476 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2477 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2478 result->auth_context_id = 0;
2480 status = auth_generic_client_prepare(result,
2482 if (!NT_STATUS_IS_OK(status)) {
2483 DEBUG(1, ("Failed to create auth_generic context: %s\n",
2484 nt_errstr(status)));
2487 status = auth_generic_set_username(auth_generic_ctx, "");
2488 if (!NT_STATUS_IS_OK(status)) {
2489 DEBUG(1, ("Failed to set username: %s\n",
2490 nt_errstr(status)));
2493 status = auth_generic_set_domain(auth_generic_ctx, "");
2494 if (!NT_STATUS_IS_OK(status)) {
2495 DEBUG(1, ("Failed to set domain: %s\n",
2496 nt_errstr(status)));
2500 status = gensec_set_credentials(auth_generic_ctx->gensec_security,
2501 auth_generic_ctx->credentials);
2502 if (!NT_STATUS_IS_OK(status)) {
2503 DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
2504 nt_errstr(status)));
2507 talloc_unlink(auth_generic_ctx, auth_generic_ctx->credentials);
2508 auth_generic_ctx->credentials = NULL;
2510 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2511 talloc_free(auth_generic_ctx);
2513 return NT_STATUS_OK;
2516 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2517 enum dcerpc_AuthType auth_type,
2518 enum dcerpc_AuthLevel auth_level,
2520 const char *target_service,
2522 const char *username,
2523 const char *password,
2524 enum credentials_use_kerberos use_kerberos,
2525 struct netlogon_creds_CredentialState *creds,
2526 struct pipe_auth_data **presult)
2528 struct auth_generic_state *auth_generic_ctx;
2529 struct pipe_auth_data *result;
2532 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2533 if (result == NULL) {
2534 return NT_STATUS_NO_MEMORY;
2537 result->auth_type = auth_type;
2538 result->auth_level = auth_level;
2539 result->auth_context_id = 1;
2541 status = auth_generic_client_prepare(result,
2543 if (!NT_STATUS_IS_OK(status)) {
2547 status = auth_generic_set_username(auth_generic_ctx, username);
2548 if (!NT_STATUS_IS_OK(status)) {
2552 status = auth_generic_set_domain(auth_generic_ctx, domain);
2553 if (!NT_STATUS_IS_OK(status)) {
2557 status = auth_generic_set_password(auth_generic_ctx, password);
2558 if (!NT_STATUS_IS_OK(status)) {
2562 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2563 if (!NT_STATUS_IS_OK(status)) {
2567 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2568 if (!NT_STATUS_IS_OK(status)) {
2572 cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos);
2573 cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
2575 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2576 if (!NT_STATUS_IS_OK(status)) {
2580 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2581 talloc_free(auth_generic_ctx);
2583 return NT_STATUS_OK;
2586 TALLOC_FREE(result);
2590 /* This routine steals the creds pointer that is passed in */
2591 static NTSTATUS rpccli_generic_bind_data_from_creds(TALLOC_CTX *mem_ctx,
2592 enum dcerpc_AuthType auth_type,
2593 enum dcerpc_AuthLevel auth_level,
2595 const char *target_service,
2596 struct cli_credentials *creds,
2597 struct pipe_auth_data **presult)
2599 struct auth_generic_state *auth_generic_ctx;
2600 struct pipe_auth_data *result;
2603 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2604 if (result == NULL) {
2605 return NT_STATUS_NO_MEMORY;
2608 result->auth_type = auth_type;
2609 result->auth_level = auth_level;
2610 result->auth_context_id = 1;
2612 status = auth_generic_client_prepare(result,
2614 if (!NT_STATUS_IS_OK(status)) {
2618 status = auth_generic_set_creds(auth_generic_ctx, creds);
2619 if (!NT_STATUS_IS_OK(status)) {
2623 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2624 if (!NT_STATUS_IS_OK(status)) {
2628 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2629 if (!NT_STATUS_IS_OK(status)) {
2633 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2634 if (!NT_STATUS_IS_OK(status)) {
2638 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2639 talloc_free(auth_generic_ctx);
2641 return NT_STATUS_OK;
2644 TALLOC_FREE(result);
2648 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2649 struct pipe_auth_data **presult)
2651 return rpccli_generic_bind_data(mem_ctx,
2652 DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
2653 DCERPC_AUTH_LEVEL_CONNECT,
2655 "host", /* target_service */
2656 NAME_NT_AUTHORITY, /* domain */
2658 NULL, /* password */
2659 CRED_USE_KERBEROS_DISABLED,
2660 NULL, /* netlogon_creds_CredentialState */
2665 * Create an rpc pipe client struct, connecting to a tcp port.
2667 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2668 const struct sockaddr_storage *ss_addr,
2670 const struct ndr_interface_table *table,
2671 struct rpc_pipe_client **presult)
2673 struct rpc_pipe_client *result;
2674 struct sockaddr_storage addr;
2678 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2679 if (result == NULL) {
2680 return NT_STATUS_NO_MEMORY;
2683 result->abstract_syntax = table->syntax_id;
2684 result->transfer_syntax = ndr_transfer_syntax_ndr;
2686 result->desthost = talloc_strdup(result, host);
2687 if (result->desthost == NULL) {
2688 status = NT_STATUS_NO_MEMORY;
2692 result->srv_name_slash = talloc_asprintf_strupper_m(
2693 result, "\\\\%s", result->desthost);
2694 if (result->srv_name_slash == NULL) {
2695 status = NT_STATUS_NO_MEMORY;
2699 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2701 if (ss_addr == NULL) {
2702 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2703 status = NT_STATUS_NOT_FOUND;
2710 status = open_socket_out(&addr, port, 60*1000, &fd);
2711 if (!NT_STATUS_IS_OK(status)) {
2714 set_socket_options(fd, lp_socket_options());
2716 status = rpc_transport_sock_init(result, fd, &result->transport);
2717 if (!NT_STATUS_IS_OK(status)) {
2722 result->transport->transport = NCACN_IP_TCP;
2724 result->binding_handle = rpccli_bh_create(result, NULL, table);
2725 if (result->binding_handle == NULL) {
2726 TALLOC_FREE(result);
2727 return NT_STATUS_NO_MEMORY;
2731 return NT_STATUS_OK;
2734 TALLOC_FREE(result);
2738 static NTSTATUS rpccli_epm_map_binding(
2739 struct dcerpc_binding_handle *epm_connection,
2740 struct dcerpc_binding *binding,
2741 TALLOC_CTX *mem_ctx,
2744 TALLOC_CTX *frame = talloc_stackframe();
2745 enum dcerpc_transport_t transport =
2746 dcerpc_binding_get_transport(binding);
2747 enum dcerpc_transport_t res_transport;
2748 struct dcerpc_binding *res_binding = NULL;
2749 struct epm_twr_t *map_tower = NULL;
2750 struct epm_twr_p_t res_towers = { .twr = NULL };
2751 struct policy_handle *entry_handle = NULL;
2752 uint32_t num_towers = 0;
2753 const uint32_t max_towers = 1;
2754 const char *endpoint = NULL;
2759 map_tower = talloc_zero(frame, struct epm_twr_t);
2760 if (map_tower == NULL) {
2764 status = dcerpc_binding_build_tower(
2765 frame, binding, &(map_tower->tower));
2766 if (!NT_STATUS_IS_OK(status)) {
2767 DBG_DEBUG("dcerpc_binding_build_tower failed: %s\n",
2772 res_towers.twr = talloc_array(frame, struct epm_twr_t, max_towers);
2773 if (res_towers.twr == NULL) {
2777 entry_handle = talloc_zero(frame, struct policy_handle);
2778 if (entry_handle == NULL) {
2782 status = dcerpc_epm_Map(
2793 if (!NT_STATUS_IS_OK(status)) {
2794 DBG_DEBUG("dcerpc_epm_Map failed: %s\n", nt_errstr(status));
2798 if (result != EPMAPPER_STATUS_OK) {
2799 DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32"\n", result);
2800 status = NT_STATUS_NOT_FOUND;
2804 if (num_towers != 1) {
2805 DBG_DEBUG("dcerpc_epm_Map returned %"PRIu32" towers\n",
2807 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2811 status = dcerpc_binding_from_tower(
2812 frame, &(res_towers.twr->tower), &res_binding);
2813 if (!NT_STATUS_IS_OK(status)) {
2814 DBG_DEBUG("dcerpc_binding_from_tower failed: %s\n",
2819 res_transport = dcerpc_binding_get_transport(res_binding);
2820 if (res_transport != transport) {
2821 DBG_DEBUG("dcerpc_epm_Map returned transport %d, "
2825 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2829 endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
2830 if (endpoint == NULL) {
2831 DBG_DEBUG("dcerpc_epm_Map returned no endpoint\n");
2832 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2836 tmp = talloc_strdup(mem_ctx, endpoint);
2842 status = NT_STATUS_OK;
2846 status = NT_STATUS_NO_MEMORY;
2852 static NTSTATUS rpccli_epm_map_interface(
2853 struct dcerpc_binding_handle *epm_connection,
2854 enum dcerpc_transport_t transport,
2855 const struct ndr_syntax_id *iface,
2856 TALLOC_CTX *mem_ctx,
2859 struct dcerpc_binding *binding = NULL;
2860 char *endpoint = NULL;
2863 status = dcerpc_parse_binding(mem_ctx, "", &binding);
2864 if (!NT_STATUS_IS_OK(status)) {
2865 DBG_DEBUG("dcerpc_parse_binding failed: %s\n",
2870 status = dcerpc_binding_set_transport(binding, transport);
2871 if (!NT_STATUS_IS_OK(status)) {
2872 DBG_DEBUG("dcerpc_binding_set_transport failed: %s\n",
2877 status = dcerpc_binding_set_abstract_syntax(binding, iface);
2878 if (!NT_STATUS_IS_OK(status)) {
2879 DBG_DEBUG("dcerpc_binding_set_abstract_syntax failed: %s\n",
2884 status = rpccli_epm_map_binding(
2885 epm_connection, binding, mem_ctx, &endpoint);
2886 if (!NT_STATUS_IS_OK(status)) {
2887 DBG_DEBUG("rpccli_epm_map_binding failed: %s\n",
2891 *pendpoint = endpoint;
2894 TALLOC_FREE(binding);
2899 * Determine the tcp port on which a dcerpc interface is listening
2900 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2903 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2904 const struct sockaddr_storage *addr,
2905 const struct ndr_interface_table *table,
2909 struct rpc_pipe_client *epm_pipe = NULL;
2910 struct pipe_auth_data *auth = NULL;
2911 char *endpoint = NULL;
2912 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2914 if (pport == NULL) {
2915 status = NT_STATUS_INVALID_PARAMETER;
2919 if (ndr_syntax_id_equal(&table->syntax_id,
2920 &ndr_table_epmapper.syntax_id)) {
2922 status = NT_STATUS_OK;
2926 /* open the connection to the endpoint mapper */
2927 status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2928 &ndr_table_epmapper,
2931 if (!NT_STATUS_IS_OK(status)) {
2935 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2936 if (!NT_STATUS_IS_OK(status)) {
2940 status = rpc_pipe_bind(epm_pipe, auth);
2941 if (!NT_STATUS_IS_OK(status)) {
2945 status = rpccli_epm_map_interface(
2946 epm_pipe->binding_handle,
2951 if (!NT_STATUS_IS_OK(status)) {
2952 DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
2957 *pport = (uint16_t)atoi(endpoint);
2960 TALLOC_FREE(tmp_ctx);
2965 * Create a rpc pipe client struct, connecting to a host via tcp.
2966 * The port is determined by asking the endpoint mapper on the given
2969 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2970 const struct sockaddr_storage *addr,
2971 const struct ndr_interface_table *table,
2972 struct rpc_pipe_client **presult)
2977 status = rpc_pipe_get_tcp_port(host, addr, table, &port);
2978 if (!NT_STATUS_IS_OK(status)) {
2982 return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2986 static NTSTATUS rpc_pipe_get_ncalrpc_name(
2987 const struct ndr_syntax_id *iface,
2988 TALLOC_CTX *mem_ctx,
2989 char **psocket_name)
2991 TALLOC_CTX *frame = talloc_stackframe();
2992 struct rpc_pipe_client *epm_pipe = NULL;
2993 struct pipe_auth_data *auth = NULL;
2994 NTSTATUS status = NT_STATUS_OK;
2997 is_epm = ndr_syntax_id_equal(iface, &ndr_table_epmapper.syntax_id);
2999 char *endpoint = talloc_strdup(mem_ctx, "EPMAPPER");
3000 if (endpoint == NULL) {
3001 status = NT_STATUS_NO_MEMORY;
3004 *psocket_name = endpoint;
3008 status = rpc_pipe_open_ncalrpc(
3009 frame, &ndr_table_epmapper, &epm_pipe);
3010 if (!NT_STATUS_IS_OK(status)) {
3011 DBG_DEBUG("rpc_pipe_open_ncalrpc failed: %s\n",
3016 status = rpccli_anon_bind_data(epm_pipe, &auth);
3017 if (!NT_STATUS_IS_OK(status)) {
3018 DBG_DEBUG("rpccli_anon_bind_data failed: %s\n",
3023 status = rpc_pipe_bind(epm_pipe, auth);
3024 if (!NT_STATUS_IS_OK(status)) {
3025 DBG_DEBUG("rpc_pipe_bind failed: %s\n", nt_errstr(status));
3029 status = rpccli_epm_map_interface(
3030 epm_pipe->binding_handle,
3035 if (!NT_STATUS_IS_OK(status)) {
3036 DBG_DEBUG("rpccli_epm_map_interface failed: %s\n",
3045 /********************************************************************
3046 Create a rpc pipe client struct, connecting to a unix domain socket
3047 ********************************************************************/
3048 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx,
3049 const struct ndr_interface_table *table,
3050 struct rpc_pipe_client **presult)
3052 char *socket_name = NULL;
3053 struct rpc_pipe_client *result;
3054 struct sockaddr_un addr = { .sun_family = AF_UNIX };
3055 socklen_t salen = sizeof(addr);
3060 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
3061 if (result == NULL) {
3062 return NT_STATUS_NO_MEMORY;
3065 status = rpc_pipe_get_ncalrpc_name(
3066 &table->syntax_id, result, &socket_name);
3067 if (!NT_STATUS_IS_OK(status)) {
3068 DBG_DEBUG("rpc_pipe_get_ncalrpc_name failed: %s\n",
3075 sizeof(addr.sun_path),
3079 if ((pathlen < 0) || ((size_t)pathlen >= sizeof(addr.sun_path))) {
3080 DBG_DEBUG("socket_path for %s too long\n", socket_name);
3081 status = NT_STATUS_NAME_TOO_LONG;
3084 TALLOC_FREE(socket_name);
3086 result->abstract_syntax = table->syntax_id;
3087 result->transfer_syntax = ndr_transfer_syntax_ndr;
3089 result->desthost = get_myname(result);
3090 if (result->desthost == NULL) {
3091 status = NT_STATUS_NO_MEMORY;
3095 result->srv_name_slash = talloc_asprintf_strupper_m(
3096 result, "\\\\%s", result->desthost);
3097 if (result->srv_name_slash == NULL) {
3098 status = NT_STATUS_NO_MEMORY;
3102 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3104 fd = socket(AF_UNIX, SOCK_STREAM, 0);
3106 status = map_nt_error_from_unix(errno);
3110 if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
3111 DBG_ERR("connect(%s) failed: %s\n",
3114 status = map_nt_error_from_unix(errno);
3118 status = rpc_transport_sock_init(result, fd, &result->transport);
3119 if (!NT_STATUS_IS_OK(status)) {
3124 result->transport->transport = NCALRPC;
3126 result->binding_handle = rpccli_bh_create(result, NULL, table);
3127 if (result->binding_handle == NULL) {
3128 status = NT_STATUS_NO_MEMORY;
3133 return NT_STATUS_OK;
3139 TALLOC_FREE(result);
3143 struct rpc_pipe_client_np_ref {
3144 struct cli_state *cli;
3145 struct rpc_pipe_client *pipe;
3148 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
3150 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
3154 /****************************************************************************
3155 Open a named pipe over SMB to a remote server.
3157 * CAVEAT CALLER OF THIS FUNCTION:
3158 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3159 * so be sure that this function is called AFTER any structure (vs pointer)
3160 * assignment of the cli. In particular, libsmbclient does structure
3161 * assignments of cli, which invalidates the data in the returned
3162 * rpc_pipe_client if this function is called before the structure assignment
3165 ****************************************************************************/
3167 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3168 const struct ndr_interface_table *table,
3169 struct rpc_pipe_client **presult)
3171 struct rpc_pipe_client *result;
3173 struct rpc_pipe_client_np_ref *np_ref;
3175 /* sanity check to protect against crashes */
3178 return NT_STATUS_INVALID_HANDLE;
3181 result = talloc_zero(NULL, struct rpc_pipe_client);
3182 if (result == NULL) {
3183 return NT_STATUS_NO_MEMORY;
3186 result->abstract_syntax = table->syntax_id;
3187 result->transfer_syntax = ndr_transfer_syntax_ndr;
3189 result->desthost = talloc_strdup(
3190 result, smbXcli_conn_remote_name(cli->conn));
3191 if (result->desthost == NULL) {
3192 TALLOC_FREE(result);
3193 return NT_STATUS_NO_MEMORY;
3196 result->srv_name_slash = talloc_asprintf_strupper_m(
3197 result, "\\\\%s", result->desthost);
3198 if (result->srv_name_slash == NULL) {
3199 TALLOC_FREE(result);
3200 return NT_STATUS_NO_MEMORY;
3203 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3205 status = rpc_transport_np_init(result, cli, table,
3206 &result->transport);
3207 if (!NT_STATUS_IS_OK(status)) {
3208 TALLOC_FREE(result);
3212 result->transport->transport = NCACN_NP;
3214 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3215 if (np_ref == NULL) {
3216 TALLOC_FREE(result);
3217 return NT_STATUS_NO_MEMORY;
3220 np_ref->pipe = result;
3222 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3223 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3225 result->binding_handle = rpccli_bh_create(result, NULL, table);
3226 if (result->binding_handle == NULL) {
3227 TALLOC_FREE(result);
3228 return NT_STATUS_NO_MEMORY;
3232 return NT_STATUS_OK;
3235 /****************************************************************************
3236 Open a pipe to a remote server.
3237 ****************************************************************************/
3239 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3240 enum dcerpc_transport_t transport,
3241 const struct ndr_interface_table *table,
3242 struct rpc_pipe_client **presult)
3244 switch (transport) {
3246 return rpc_pipe_open_tcp(NULL,
3247 smbXcli_conn_remote_name(cli->conn),
3248 smbXcli_conn_remote_sockaddr(cli->conn),
3251 return rpc_pipe_open_np(cli, table, presult);
3253 return NT_STATUS_NOT_IMPLEMENTED;
3257 /****************************************************************************
3258 Open a named pipe to an SMB server and bind anonymously.
3259 ****************************************************************************/
3261 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3262 enum dcerpc_transport_t transport,
3263 const struct ndr_interface_table *table,
3264 struct rpc_pipe_client **presult)
3266 struct rpc_pipe_client *result;
3267 struct pipe_auth_data *auth;
3270 status = cli_rpc_pipe_open(cli, transport, table, &result);
3271 if (!NT_STATUS_IS_OK(status)) {
3275 status = rpccli_anon_bind_data(result, &auth);
3276 if (!NT_STATUS_IS_OK(status)) {
3277 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3278 nt_errstr(status)));
3279 TALLOC_FREE(result);
3284 * This is a bit of an abstraction violation due to the fact that an
3285 * anonymous bind on an authenticated SMB inherits the user/domain
3286 * from the enclosing SMB creds
3289 if (transport == NCACN_NP) {
3290 struct smbXcli_session *session;
3292 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3293 session = cli->smb2.session;
3295 session = cli->smb1.session;
3298 status = smbXcli_session_application_key(session, auth,
3299 &auth->transport_session_key);
3300 if (!NT_STATUS_IS_OK(status)) {
3301 auth->transport_session_key = data_blob_null;
3305 status = rpc_pipe_bind(result, auth);
3306 if (!NT_STATUS_IS_OK(status)) {
3308 if (ndr_syntax_id_equal(&table->syntax_id,
3309 &ndr_table_dssetup.syntax_id)) {
3310 /* non AD domains just don't have this pipe, avoid
3311 * level 0 statement in that case - gd */
3314 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3315 "%s failed with error %s\n",
3317 nt_errstr(status) ));
3318 TALLOC_FREE(result);
3322 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3323 "%s and bound anonymously.\n",
3328 return NT_STATUS_OK;
3331 /****************************************************************************
3332 ****************************************************************************/
3334 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3335 const struct ndr_interface_table *table,
3336 struct rpc_pipe_client **presult)
3338 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3342 /****************************************************************************
3343 Open a named pipe to an SMB server and bind using the mech specified
3345 This routine references the creds pointer that is passed in
3346 ****************************************************************************/
3348 NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
3349 const struct ndr_interface_table *table,
3350 enum dcerpc_transport_t transport,
3351 enum dcerpc_AuthType auth_type,
3352 enum dcerpc_AuthLevel auth_level,
3354 struct cli_credentials *creds,
3355 struct rpc_pipe_client **presult)
3357 struct rpc_pipe_client *result;
3358 struct pipe_auth_data *auth = NULL;
3359 const char *target_service = table->authservices->names[0];
3362 status = cli_rpc_pipe_open(cli, transport, table, &result);
3363 if (!NT_STATUS_IS_OK(status)) {
3367 status = rpccli_generic_bind_data_from_creds(result,
3368 auth_type, auth_level,
3369 server, target_service,
3372 if (!NT_STATUS_IS_OK(status)) {
3373 DBG_ERR("rpccli_generic_bind_data_from_creds returned %s\n",
3378 status = rpc_pipe_bind(result, auth);
3379 if (!NT_STATUS_IS_OK(status)) {
3380 DBG_ERR("cli_rpc_pipe_bind failed with error %s\n",
3385 DBG_DEBUG("opened pipe %s to machine %s and bound as user %s.\n",
3388 cli_credentials_get_unparsed_name(creds, talloc_tos()));
3391 return NT_STATUS_OK;
3395 TALLOC_FREE(result);
3399 NTSTATUS cli_rpc_pipe_open_bind_schannel(
3400 struct cli_state *cli,
3401 const struct ndr_interface_table *table,
3402 enum dcerpc_transport_t transport,
3403 struct netlogon_creds_cli_context *netlogon_creds,
3404 struct rpc_pipe_client **_rpccli)
3406 struct rpc_pipe_client *rpccli;
3407 struct pipe_auth_data *rpcauth;
3408 const char *target_service = table->authservices->names[0];
3409 struct cli_credentials *cli_creds;
3410 enum dcerpc_AuthLevel auth_level;
3413 status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
3414 if (!NT_STATUS_IS_OK(status)) {
3418 auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
3420 status = netlogon_creds_bind_cli_credentials(
3421 netlogon_creds, rpccli, &cli_creds);
3422 if (!NT_STATUS_IS_OK(status)) {
3423 DBG_DEBUG("netlogon_creds_bind_cli_credentials failed: %s\n",
3425 TALLOC_FREE(rpccli);
3429 status = rpccli_generic_bind_data_from_creds(rpccli,
3430 DCERPC_AUTH_TYPE_SCHANNEL,
3436 if (!NT_STATUS_IS_OK(status)) {
3437 DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
3438 nt_errstr(status)));
3439 TALLOC_FREE(rpccli);
3443 status = rpc_pipe_bind(rpccli, rpcauth);
3445 /* No TALLOC_FREE, gensec takes references */
3446 talloc_unlink(rpccli, cli_creds);
3449 if (!NT_STATUS_IS_OK(status)) {
3450 DBG_DEBUG("rpc_pipe_bind failed with error %s\n",
3452 TALLOC_FREE(rpccli);
3458 return NT_STATUS_OK;
3461 NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
3462 const struct ndr_interface_table *table,
3463 enum dcerpc_transport_t transport,
3464 struct netlogon_creds_cli_context *netlogon_creds,
3465 struct rpc_pipe_client **_rpccli)
3467 TALLOC_CTX *frame = talloc_stackframe();
3468 struct rpc_pipe_client *rpccli;
3469 struct netlogon_creds_cli_lck *lck;
3472 status = netlogon_creds_cli_lck(
3473 netlogon_creds, NETLOGON_CREDS_CLI_LCK_EXCLUSIVE,
3475 if (!NT_STATUS_IS_OK(status)) {
3476 DBG_WARNING("netlogon_creds_cli_lck returned %s\n",
3482 status = cli_rpc_pipe_open_bind_schannel(
3483 cli, table, transport, netlogon_creds, &rpccli);
3484 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3485 netlogon_creds_cli_delete_lck(netlogon_creds);
3487 if (!NT_STATUS_IS_OK(status)) {
3488 DBG_DEBUG("cli_rpc_pipe_open_bind_schannel failed: %s\n",
3494 if (ndr_syntax_id_equal(&table->syntax_id,
3495 &ndr_table_netlogon.syntax_id)) {
3496 status = netlogon_creds_cli_check(netlogon_creds,
3497 rpccli->binding_handle,
3499 if (!NT_STATUS_IS_OK(status)) {
3500 DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
3501 nt_errstr(status)));
3507 DBG_DEBUG("opened pipe %s to machine %s with key %s "
3508 "and bound using schannel.\n",
3509 table->name, rpccli->desthost,
3510 netlogon_creds_cli_debug_string(netlogon_creds, lck));
3515 return NT_STATUS_OK;
3518 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3519 struct rpc_pipe_client *cli,
3520 DATA_BLOB *session_key)
3523 struct pipe_auth_data *a;
3524 struct gensec_security *gensec_security;
3525 DATA_BLOB sk = data_blob_null;
3526 bool make_dup = false;
3528 if (!session_key || !cli) {
3529 return NT_STATUS_INVALID_PARAMETER;
3535 return NT_STATUS_INVALID_PARAMETER;
3538 switch (cli->auth->auth_type) {
3539 case DCERPC_AUTH_TYPE_NONE:
3540 sk = data_blob_const(a->transport_session_key.data,
3541 a->transport_session_key.length);
3545 gensec_security = a->auth_ctx;
3546 status = gensec_session_key(gensec_security, mem_ctx, &sk);
3547 if (!NT_STATUS_IS_OK(status)) {
3555 return NT_STATUS_NO_USER_SESSION_KEY;
3559 *session_key = data_blob_dup_talloc(mem_ctx, sk);
3564 return NT_STATUS_OK;