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"
35 #include "libsmb/libsmb.h"
36 #include "auth/gensec/gensec.h"
37 #include "auth/credentials/credentials.h"
38 #include "../libcli/smb/smbXcli_base.h"
39 #include "librpc/rpc/dcerpc_connection.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;
398 NTSTATUS ret = NT_STATUS_OK;
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;
1235 NTSTATUS ret = NT_STATUS_OK;
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 blobl
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)
2164 if (rpc_cli->transport == NULL) {
2165 return RPCCLI_DEFAULT_TIMEOUT;
2168 if (rpc_cli->transport->set_timeout == NULL) {
2169 return RPCCLI_DEFAULT_TIMEOUT;
2172 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
2174 return RPCCLI_DEFAULT_TIMEOUT;
2180 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
2182 if (rpc_cli == NULL) {
2186 if (rpc_cli->transport == NULL) {
2190 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
2193 struct rpccli_bh_state {
2194 struct rpc_pipe_client *rpc_cli;
2197 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
2199 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2200 struct rpccli_bh_state);
2202 return rpccli_is_connected(hs->rpc_cli);
2205 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle *h,
2208 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2209 struct rpccli_bh_state);
2211 return rpccli_set_timeout(hs->rpc_cli, timeout);
2214 static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
2215 enum dcerpc_AuthType *auth_type,
2216 enum dcerpc_AuthLevel *auth_level)
2218 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2219 struct rpccli_bh_state);
2221 if (hs->rpc_cli == NULL) {
2225 if (hs->rpc_cli->auth == NULL) {
2229 *auth_type = hs->rpc_cli->auth->auth_type;
2230 *auth_level = hs->rpc_cli->auth->auth_level;
2233 struct rpccli_bh_raw_call_state {
2239 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2241 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2242 struct tevent_context *ev,
2243 struct dcerpc_binding_handle *h,
2244 const struct GUID *object,
2247 const uint8_t *in_data,
2250 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2251 struct rpccli_bh_state);
2252 struct tevent_req *req;
2253 struct rpccli_bh_raw_call_state *state;
2255 struct tevent_req *subreq;
2257 req = tevent_req_create(mem_ctx, &state,
2258 struct rpccli_bh_raw_call_state);
2262 state->in_data.data = discard_const_p(uint8_t, in_data);
2263 state->in_data.length = in_length;
2265 ok = rpccli_bh_is_connected(h);
2267 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2268 return tevent_req_post(req, ev);
2271 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2272 opnum, object, &state->in_data);
2273 if (tevent_req_nomem(subreq, req)) {
2274 return tevent_req_post(req, ev);
2276 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2281 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2283 struct tevent_req *req =
2284 tevent_req_callback_data(subreq,
2286 struct rpccli_bh_raw_call_state *state =
2287 tevent_req_data(req,
2288 struct rpccli_bh_raw_call_state);
2291 state->out_flags = 0;
2293 /* TODO: support bigendian responses */
2295 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2296 TALLOC_FREE(subreq);
2297 if (!NT_STATUS_IS_OK(status)) {
2298 tevent_req_nterror(req, status);
2302 tevent_req_done(req);
2305 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2306 TALLOC_CTX *mem_ctx,
2309 uint32_t *out_flags)
2311 struct rpccli_bh_raw_call_state *state =
2312 tevent_req_data(req,
2313 struct rpccli_bh_raw_call_state);
2316 if (tevent_req_is_nterror(req, &status)) {
2317 tevent_req_received(req);
2321 *out_data = talloc_move(mem_ctx, &state->out_data.data);
2322 *out_length = state->out_data.length;
2323 *out_flags = state->out_flags;
2324 tevent_req_received(req);
2325 return NT_STATUS_OK;
2328 struct rpccli_bh_disconnect_state {
2332 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2333 struct tevent_context *ev,
2334 struct dcerpc_binding_handle *h)
2336 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2337 struct rpccli_bh_state);
2338 struct tevent_req *req;
2339 struct rpccli_bh_disconnect_state *state;
2342 req = tevent_req_create(mem_ctx, &state,
2343 struct rpccli_bh_disconnect_state);
2348 ok = rpccli_bh_is_connected(h);
2350 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
2351 return tevent_req_post(req, ev);
2355 * TODO: do a real async disconnect ...
2357 * For now we do it sync...
2359 TALLOC_FREE(hs->rpc_cli->transport);
2362 tevent_req_done(req);
2363 return tevent_req_post(req, ev);
2366 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2370 if (tevent_req_is_nterror(req, &status)) {
2371 tevent_req_received(req);
2375 tevent_req_received(req);
2376 return NT_STATUS_OK;
2379 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2384 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2386 const void *_struct_ptr,
2387 const struct ndr_interface_call *call)
2389 void *struct_ptr = discard_const(_struct_ptr);
2391 if (DEBUGLEVEL < 10) {
2395 if (ndr_flags & NDR_IN) {
2396 ndr_print_function_debug(call->ndr_print,
2401 if (ndr_flags & NDR_OUT) {
2402 ndr_print_function_debug(call->ndr_print,
2409 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2411 .is_connected = rpccli_bh_is_connected,
2412 .set_timeout = rpccli_bh_set_timeout,
2413 .auth_info = rpccli_bh_auth_info,
2414 .raw_call_send = rpccli_bh_raw_call_send,
2415 .raw_call_recv = rpccli_bh_raw_call_recv,
2416 .disconnect_send = rpccli_bh_disconnect_send,
2417 .disconnect_recv = rpccli_bh_disconnect_recv,
2419 .ref_alloc = rpccli_bh_ref_alloc,
2420 .do_ndr_print = rpccli_bh_do_ndr_print,
2423 /* initialise a rpc_pipe_client binding handle */
2424 struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
2425 const struct GUID *object,
2426 const struct ndr_interface_table *table)
2428 struct dcerpc_binding_handle *h;
2429 struct rpccli_bh_state *hs;
2431 h = dcerpc_binding_handle_create(c,
2436 struct rpccli_bh_state,
2446 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2447 struct pipe_auth_data **presult)
2449 struct pipe_auth_data *result;
2450 struct auth_generic_state *auth_generic_ctx;
2453 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2454 if (result == NULL) {
2455 return NT_STATUS_NO_MEMORY;
2458 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2459 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2460 result->auth_context_id = 0;
2462 status = auth_generic_client_prepare(result,
2464 if (!NT_STATUS_IS_OK(status)) {
2465 DEBUG(1, ("Failed to create auth_generic context: %s\n",
2466 nt_errstr(status)));
2469 status = auth_generic_set_username(auth_generic_ctx, "");
2470 if (!NT_STATUS_IS_OK(status)) {
2471 DEBUG(1, ("Failed to set username: %s\n",
2472 nt_errstr(status)));
2475 status = auth_generic_set_domain(auth_generic_ctx, "");
2476 if (!NT_STATUS_IS_OK(status)) {
2477 DEBUG(1, ("Failed to set domain: %s\n",
2478 nt_errstr(status)));
2482 status = gensec_set_credentials(auth_generic_ctx->gensec_security,
2483 auth_generic_ctx->credentials);
2484 if (!NT_STATUS_IS_OK(status)) {
2485 DEBUG(1, ("Failed to set GENSEC credentials: %s\n",
2486 nt_errstr(status)));
2489 talloc_unlink(auth_generic_ctx, auth_generic_ctx->credentials);
2490 auth_generic_ctx->credentials = NULL;
2492 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2493 talloc_free(auth_generic_ctx);
2495 return NT_STATUS_OK;
2498 static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
2499 enum dcerpc_AuthType auth_type,
2500 enum dcerpc_AuthLevel auth_level,
2502 const char *target_service,
2504 const char *username,
2505 const char *password,
2506 enum credentials_use_kerberos use_kerberos,
2507 struct netlogon_creds_CredentialState *creds,
2508 struct pipe_auth_data **presult)
2510 struct auth_generic_state *auth_generic_ctx;
2511 struct pipe_auth_data *result;
2514 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2515 if (result == NULL) {
2516 return NT_STATUS_NO_MEMORY;
2519 result->auth_type = auth_type;
2520 result->auth_level = auth_level;
2521 result->auth_context_id = 1;
2523 status = auth_generic_client_prepare(result,
2525 if (!NT_STATUS_IS_OK(status)) {
2529 status = auth_generic_set_username(auth_generic_ctx, username);
2530 if (!NT_STATUS_IS_OK(status)) {
2534 status = auth_generic_set_domain(auth_generic_ctx, domain);
2535 if (!NT_STATUS_IS_OK(status)) {
2539 status = auth_generic_set_password(auth_generic_ctx, password);
2540 if (!NT_STATUS_IS_OK(status)) {
2544 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2545 if (!NT_STATUS_IS_OK(status)) {
2549 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2550 if (!NT_STATUS_IS_OK(status)) {
2554 cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos);
2555 cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
2557 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2558 if (!NT_STATUS_IS_OK(status)) {
2562 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2563 talloc_free(auth_generic_ctx);
2565 return NT_STATUS_OK;
2568 TALLOC_FREE(result);
2572 /* This routine steals the creds pointer that is passed in */
2573 static NTSTATUS rpccli_generic_bind_data_from_creds(TALLOC_CTX *mem_ctx,
2574 enum dcerpc_AuthType auth_type,
2575 enum dcerpc_AuthLevel auth_level,
2577 const char *target_service,
2578 struct cli_credentials *creds,
2579 struct pipe_auth_data **presult)
2581 struct auth_generic_state *auth_generic_ctx;
2582 struct pipe_auth_data *result;
2585 result = talloc_zero(mem_ctx, struct pipe_auth_data);
2586 if (result == NULL) {
2587 return NT_STATUS_NO_MEMORY;
2590 result->auth_type = auth_type;
2591 result->auth_level = auth_level;
2592 result->auth_context_id = 1;
2594 status = auth_generic_client_prepare(result,
2596 if (!NT_STATUS_IS_OK(status)) {
2600 status = auth_generic_set_creds(auth_generic_ctx, creds);
2601 if (!NT_STATUS_IS_OK(status)) {
2605 status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
2606 if (!NT_STATUS_IS_OK(status)) {
2610 status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
2611 if (!NT_STATUS_IS_OK(status)) {
2615 status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
2616 if (!NT_STATUS_IS_OK(status)) {
2620 result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
2621 talloc_free(auth_generic_ctx);
2623 return NT_STATUS_OK;
2626 TALLOC_FREE(result);
2630 NTSTATUS rpccli_ncalrpc_bind_data(TALLOC_CTX *mem_ctx,
2631 struct pipe_auth_data **presult)
2633 return rpccli_generic_bind_data(mem_ctx,
2634 DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
2635 DCERPC_AUTH_LEVEL_CONNECT,
2637 "host", /* target_service */
2638 NAME_NT_AUTHORITY, /* domain */
2640 NULL, /* password */
2641 CRED_DONT_USE_KERBEROS,
2642 NULL, /* netlogon_creds_CredentialState */
2647 * Create an rpc pipe client struct, connecting to a tcp port.
2649 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2650 const struct sockaddr_storage *ss_addr,
2652 const struct ndr_interface_table *table,
2653 struct rpc_pipe_client **presult)
2655 struct rpc_pipe_client *result;
2656 struct sockaddr_storage addr;
2660 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2661 if (result == NULL) {
2662 return NT_STATUS_NO_MEMORY;
2665 result->abstract_syntax = table->syntax_id;
2666 result->transfer_syntax = ndr_transfer_syntax_ndr;
2668 result->desthost = talloc_strdup(result, host);
2669 result->srv_name_slash = talloc_asprintf_strupper_m(
2670 result, "\\\\%s", result->desthost);
2671 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2672 status = NT_STATUS_NO_MEMORY;
2676 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2678 if (ss_addr == NULL) {
2679 if (!resolve_name(host, &addr, NBT_NAME_SERVER, false)) {
2680 status = NT_STATUS_NOT_FOUND;
2687 status = open_socket_out(&addr, port, 60*1000, &fd);
2688 if (!NT_STATUS_IS_OK(status)) {
2691 set_socket_options(fd, lp_socket_options());
2693 status = rpc_transport_sock_init(result, fd, &result->transport);
2694 if (!NT_STATUS_IS_OK(status)) {
2699 result->transport->transport = NCACN_IP_TCP;
2701 result->assoc = dcerpc_association_create(result, 0);
2702 result->conn = dcerpc_connection_create(result, result->assoc,
2703 &result->transport->stream);
2704 result->pres = dcerpc_presentation_allocate(result, result->conn, table,
2705 &ndr_transfer_syntax_ndr);
2706 result->sec = dcerpc_security_allocate(result, result->conn,
2707 DCERPC_AUTH_TYPE_NONE,
2708 DCERPC_AUTH_LEVEL_NONE,
2711 result->binding_handle = rpccli_bh_create(result, NULL, table);
2712 if (result->binding_handle == NULL) {
2713 TALLOC_FREE(result);
2714 return NT_STATUS_NO_MEMORY;
2718 return NT_STATUS_OK;
2721 TALLOC_FREE(result);
2726 * Determine the tcp port on which a dcerpc interface is listening
2727 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2730 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2731 const struct sockaddr_storage *addr,
2732 const struct ndr_interface_table *table,
2736 struct rpc_pipe_client *epm_pipe = NULL;
2737 struct dcerpc_binding_handle *epm_handle = NULL;
2738 struct pipe_auth_data *auth = NULL;
2739 struct dcerpc_binding *map_binding = NULL;
2740 struct dcerpc_binding *res_binding = NULL;
2741 enum dcerpc_transport_t transport;
2742 const char *endpoint = NULL;
2743 struct epm_twr_t *map_tower = NULL;
2744 struct epm_twr_t *res_towers = NULL;
2745 struct policy_handle *entry_handle = NULL;
2746 uint32_t num_towers = 0;
2747 uint32_t max_towers = 1;
2748 struct epm_twr_p_t towers;
2749 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2750 uint32_t result = 0;
2752 if (pport == NULL) {
2753 status = NT_STATUS_INVALID_PARAMETER;
2757 if (ndr_syntax_id_equal(&table->syntax_id,
2758 &ndr_table_epmapper.syntax_id)) {
2760 status = NT_STATUS_OK;
2764 /* open the connection to the endpoint mapper */
2765 status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
2766 &ndr_table_epmapper,
2769 if (!NT_STATUS_IS_OK(status)) {
2772 epm_handle = epm_pipe->binding_handle;
2774 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2775 if (!NT_STATUS_IS_OK(status)) {
2779 status = rpc_pipe_bind(epm_pipe, auth);
2780 if (!NT_STATUS_IS_OK(status)) {
2784 /* create tower for asking the epmapper */
2786 status = dcerpc_parse_binding(tmp_ctx, "ncacn_ip_tcp:[135]",
2788 if (!NT_STATUS_IS_OK(status)) {
2792 status = dcerpc_binding_set_abstract_syntax(map_binding,
2794 if (!NT_STATUS_IS_OK(status)) {
2798 map_tower = talloc_zero(tmp_ctx, struct epm_twr_t);
2799 if (map_tower == NULL) {
2800 status = NT_STATUS_NO_MEMORY;
2804 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2805 &(map_tower->tower));
2806 if (!NT_STATUS_IS_OK(status)) {
2810 /* allocate further parameters for the epm_Map call */
2812 res_towers = talloc_array(tmp_ctx, struct epm_twr_t, max_towers);
2813 if (res_towers == NULL) {
2814 status = NT_STATUS_NO_MEMORY;
2817 towers.twr = res_towers;
2819 entry_handle = talloc_zero(tmp_ctx, struct policy_handle);
2820 if (entry_handle == NULL) {
2821 status = NT_STATUS_NO_MEMORY;
2825 /* ask the endpoint mapper for the port */
2827 status = dcerpc_epm_Map(epm_handle,
2829 discard_const_p(struct GUID,
2830 &(table->syntax_id.uuid)),
2838 if (!NT_STATUS_IS_OK(status)) {
2842 if (result != EPMAPPER_STATUS_OK) {
2843 status = NT_STATUS_UNSUCCESSFUL;
2847 if (num_towers != 1) {
2848 status = NT_STATUS_UNSUCCESSFUL;
2852 /* extract the port from the answer */
2854 status = dcerpc_binding_from_tower(tmp_ctx,
2855 &(towers.twr->tower),
2857 if (!NT_STATUS_IS_OK(status)) {
2861 transport = dcerpc_binding_get_transport(res_binding);
2862 endpoint = dcerpc_binding_get_string_option(res_binding, "endpoint");
2864 /* are further checks here necessary? */
2865 if (transport != NCACN_IP_TCP) {
2866 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2870 if (endpoint == NULL) {
2871 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2875 *pport = (uint16_t)atoi(endpoint);
2878 TALLOC_FREE(tmp_ctx);
2883 * Create a rpc pipe client struct, connecting to a host via tcp.
2884 * The port is determined by asking the endpoint mapper on the given
2887 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2888 const struct sockaddr_storage *addr,
2889 const struct ndr_interface_table *table,
2890 struct rpc_pipe_client **presult)
2895 status = rpc_pipe_get_tcp_port(host, addr, table, &port);
2896 if (!NT_STATUS_IS_OK(status)) {
2900 return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
2904 /********************************************************************
2905 Create a rpc pipe client struct, connecting to a unix domain socket
2906 ********************************************************************/
2907 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2908 const struct ndr_interface_table *table,
2909 struct rpc_pipe_client **presult)
2911 struct rpc_pipe_client *result;
2912 struct sockaddr_un addr;
2917 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2918 if (result == NULL) {
2919 return NT_STATUS_NO_MEMORY;
2922 result->abstract_syntax = table->syntax_id;
2923 result->transfer_syntax = ndr_transfer_syntax_ndr;
2925 result->desthost = get_myname(result);
2926 result->srv_name_slash = talloc_asprintf_strupper_m(
2927 result, "\\\\%s", result->desthost);
2928 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2929 status = NT_STATUS_NO_MEMORY;
2933 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2935 fd = socket(AF_UNIX, SOCK_STREAM, 0);
2937 status = map_nt_error_from_unix(errno);
2942 addr.sun_family = AF_UNIX;
2943 strlcpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2944 salen = sizeof(struct sockaddr_un);
2946 if (connect(fd, (struct sockaddr *)(void *)&addr, salen) == -1) {
2947 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2950 return map_nt_error_from_unix(errno);
2953 status = rpc_transport_sock_init(result, fd, &result->transport);
2954 if (!NT_STATUS_IS_OK(status)) {
2959 result->transport->transport = NCALRPC;
2961 result->assoc = dcerpc_association_create(result, 0);
2962 result->conn = dcerpc_connection_create(result, result->assoc,
2963 &result->transport->stream);
2964 result->pres = dcerpc_presentation_allocate(result, result->conn, table,
2965 &ndr_transfer_syntax_ndr);
2966 result->sec = dcerpc_security_allocate(result, result->conn,
2967 DCERPC_AUTH_TYPE_NONE,
2968 DCERPC_AUTH_LEVEL_NONE,
2971 result->binding_handle = rpccli_bh_create(result, NULL, table);
2972 if (result->binding_handle == NULL) {
2973 TALLOC_FREE(result);
2974 return NT_STATUS_NO_MEMORY;
2978 return NT_STATUS_OK;
2981 TALLOC_FREE(result);
2985 struct rpc_pipe_client_np_ref {
2986 struct cli_state *cli;
2987 struct rpc_pipe_client *pipe;
2990 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2992 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2996 /****************************************************************************
2997 Open a named pipe over SMB to a remote server.
2999 * CAVEAT CALLER OF THIS FUNCTION:
3000 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
3001 * so be sure that this function is called AFTER any structure (vs pointer)
3002 * assignment of the cli. In particular, libsmbclient does structure
3003 * assignments of cli, which invalidates the data in the returned
3004 * rpc_pipe_client if this function is called before the structure assignment
3007 ****************************************************************************/
3009 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
3010 const struct ndr_interface_table *table,
3011 struct rpc_pipe_client **presult)
3013 struct rpc_pipe_client *result;
3015 struct rpc_pipe_client_np_ref *np_ref;
3017 /* sanity check to protect against crashes */
3020 return NT_STATUS_INVALID_HANDLE;
3023 result = talloc_zero(NULL, struct rpc_pipe_client);
3024 if (result == NULL) {
3025 return NT_STATUS_NO_MEMORY;
3028 result->abstract_syntax = table->syntax_id;
3029 result->transfer_syntax = ndr_transfer_syntax_ndr;
3030 result->desthost = talloc_strdup(result, smbXcli_conn_remote_name(cli->conn));
3031 result->srv_name_slash = talloc_asprintf_strupper_m(
3032 result, "\\\\%s", result->desthost);
3034 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
3036 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
3037 TALLOC_FREE(result);
3038 return NT_STATUS_NO_MEMORY;
3041 status = rpc_transport_np_init(result, cli, table,
3042 &result->transport);
3043 if (!NT_STATUS_IS_OK(status)) {
3044 TALLOC_FREE(result);
3048 result->transport->transport = NCACN_NP;
3050 result->assoc = dcerpc_association_create(result, 0);
3051 result->conn = dcerpc_connection_create(result, result->assoc,
3052 &result->transport->stream);
3053 result->pres = dcerpc_presentation_allocate(result, result->conn, table,
3054 &ndr_transfer_syntax_ndr);
3055 result->sec = dcerpc_security_allocate(result, result->conn,
3056 DCERPC_AUTH_TYPE_NONE,
3057 DCERPC_AUTH_LEVEL_NONE,
3060 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
3061 if (np_ref == NULL) {
3062 TALLOC_FREE(result);
3063 return NT_STATUS_NO_MEMORY;
3066 np_ref->pipe = result;
3068 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
3069 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
3071 result->binding_handle = rpccli_bh_create(result, NULL, table);
3072 if (result->binding_handle == NULL) {
3073 TALLOC_FREE(result);
3074 return NT_STATUS_NO_MEMORY;
3078 return NT_STATUS_OK;
3081 /****************************************************************************
3082 Open a pipe to a remote server.
3083 ****************************************************************************/
3085 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
3086 enum dcerpc_transport_t transport,
3087 const struct ndr_interface_table *table,
3088 struct rpc_pipe_client **presult)
3090 switch (transport) {
3092 return rpc_pipe_open_tcp(NULL,
3093 smbXcli_conn_remote_name(cli->conn),
3094 smbXcli_conn_remote_sockaddr(cli->conn),
3097 return rpc_pipe_open_np(cli, table, presult);
3099 return NT_STATUS_NOT_IMPLEMENTED;
3103 /****************************************************************************
3104 Open a named pipe to an SMB server and bind anonymously.
3105 ****************************************************************************/
3107 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
3108 enum dcerpc_transport_t transport,
3109 const struct ndr_interface_table *table,
3110 struct rpc_pipe_client **presult)
3112 struct rpc_pipe_client *result;
3113 struct pipe_auth_data *auth;
3116 status = cli_rpc_pipe_open(cli, transport, table, &result);
3117 if (!NT_STATUS_IS_OK(status)) {
3121 status = rpccli_anon_bind_data(result, &auth);
3122 if (!NT_STATUS_IS_OK(status)) {
3123 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
3124 nt_errstr(status)));
3125 TALLOC_FREE(result);
3130 * This is a bit of an abstraction violation due to the fact that an
3131 * anonymous bind on an authenticated SMB inherits the user/domain
3132 * from the enclosing SMB creds
3135 if (transport == NCACN_NP) {
3136 struct smbXcli_session *session;
3138 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3139 session = cli->smb2.session;
3141 session = cli->smb1.session;
3144 status = smbXcli_session_application_key(session, auth,
3145 &auth->transport_session_key);
3146 if (!NT_STATUS_IS_OK(status)) {
3147 auth->transport_session_key = data_blob_null;
3151 status = rpc_pipe_bind(result, auth);
3152 if (!NT_STATUS_IS_OK(status)) {
3154 if (ndr_syntax_id_equal(&table->syntax_id,
3155 &ndr_table_dssetup.syntax_id)) {
3156 /* non AD domains just don't have this pipe, avoid
3157 * level 0 statement in that case - gd */
3160 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
3161 "%s failed with error %s\n",
3163 nt_errstr(status) ));
3164 TALLOC_FREE(result);
3168 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
3169 "%s and bound anonymously.\n",
3174 return NT_STATUS_OK;
3177 /****************************************************************************
3178 ****************************************************************************/
3180 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
3181 const struct ndr_interface_table *table,
3182 struct rpc_pipe_client **presult)
3184 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
3188 /****************************************************************************
3189 Open a named pipe to an SMB server and bind using the mech specified
3191 This routine references the creds pointer that is passed in
3192 ****************************************************************************/
3194 NTSTATUS cli_rpc_pipe_open_with_creds(struct cli_state *cli,
3195 const struct ndr_interface_table *table,
3196 enum dcerpc_transport_t transport,
3197 enum dcerpc_AuthType auth_type,
3198 enum dcerpc_AuthLevel auth_level,
3200 struct cli_credentials *creds,
3201 struct rpc_pipe_client **presult)
3203 struct rpc_pipe_client *result;
3204 struct pipe_auth_data *auth = NULL;
3205 const char *target_service = table->authservices->names[0];
3209 status = cli_rpc_pipe_open(cli, transport, table, &result);
3210 if (!NT_STATUS_IS_OK(status)) {
3214 status = rpccli_generic_bind_data_from_creds(result,
3215 auth_type, auth_level,
3216 server, target_service,
3219 if (!NT_STATUS_IS_OK(status)) {
3220 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3221 nt_errstr(status)));
3225 status = rpc_pipe_bind(result, auth);
3226 if (!NT_STATUS_IS_OK(status)) {
3227 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
3228 nt_errstr(status) ));
3232 DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
3233 "machine %s and bound as user %s.\n", table->name,
3234 result->desthost, cli_credentials_get_unparsed_name(creds, talloc_tos())));
3237 return NT_STATUS_OK;
3241 TALLOC_FREE(result);
3245 /****************************************************************************
3246 Open a named pipe to an SMB server and bind using the mech specified
3248 This routine steals the creds pointer that is passed in
3249 ****************************************************************************/
3251 NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
3252 const struct ndr_interface_table *table,
3253 enum dcerpc_transport_t transport,
3254 enum credentials_use_kerberos use_kerberos,
3255 enum dcerpc_AuthType auth_type,
3256 enum dcerpc_AuthLevel auth_level,
3259 const char *username,
3260 const char *password,
3261 struct rpc_pipe_client **presult)
3263 struct rpc_pipe_client *result;
3264 struct pipe_auth_data *auth = NULL;
3265 const char *target_service = table->authservices->names[0];
3269 status = cli_rpc_pipe_open(cli, transport, table, &result);
3270 if (!NT_STATUS_IS_OK(status)) {
3274 status = rpccli_generic_bind_data(result,
3275 auth_type, auth_level,
3276 server, target_service,
3277 domain, username, password,
3278 CRED_AUTO_USE_KERBEROS,
3281 if (!NT_STATUS_IS_OK(status)) {
3282 DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
3283 nt_errstr(status)));
3287 status = rpc_pipe_bind(result, auth);
3288 if (!NT_STATUS_IS_OK(status)) {
3289 DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
3290 nt_errstr(status) ));
3294 DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
3295 "machine %s and bound as user %s\\%s.\n", table->name,
3296 result->desthost, domain, username));
3299 return NT_STATUS_OK;
3303 TALLOC_FREE(result);
3307 NTSTATUS cli_rpc_pipe_open_bind_schannel(
3308 struct cli_state *cli,
3309 const struct ndr_interface_table *table,
3310 enum dcerpc_transport_t transport,
3311 struct netlogon_creds_cli_context *netlogon_creds,
3312 struct rpc_pipe_client **_rpccli)
3314 struct rpc_pipe_client *rpccli;
3315 struct pipe_auth_data *rpcauth;
3316 const char *target_service = table->authservices->names[0];
3317 struct cli_credentials *cli_creds;
3318 enum dcerpc_AuthLevel auth_level;
3321 status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
3322 if (!NT_STATUS_IS_OK(status)) {
3326 auth_level = netlogon_creds_cli_auth_level(netlogon_creds);
3328 status = netlogon_creds_bind_cli_credentials(
3329 netlogon_creds, rpccli, &cli_creds);
3330 if (!NT_STATUS_IS_OK(status)) {
3331 DBG_DEBUG("netlogon_creds_bind_cli_credentials failed: %s\n",
3333 TALLOC_FREE(rpccli);
3337 status = rpccli_generic_bind_data_from_creds(rpccli,
3338 DCERPC_AUTH_TYPE_SCHANNEL,
3344 if (!NT_STATUS_IS_OK(status)) {
3345 DEBUG(0, ("rpccli_generic_bind_data_from_creds returned %s\n",
3346 nt_errstr(status)));
3347 TALLOC_FREE(rpccli);
3351 status = rpc_pipe_bind(rpccli, rpcauth);
3353 /* No TALLOC_FREE, gensec takes references */
3354 talloc_unlink(rpccli, cli_creds);
3357 if (!NT_STATUS_IS_OK(status)) {
3358 DBG_DEBUG("rpc_pipe_bind failed with error %s\n",
3360 TALLOC_FREE(rpccli);
3366 return NT_STATUS_OK;
3369 NTSTATUS cli_rpc_pipe_open_schannel_with_creds(struct cli_state *cli,
3370 const struct ndr_interface_table *table,
3371 enum dcerpc_transport_t transport,
3372 struct netlogon_creds_cli_context *netlogon_creds,
3373 struct rpc_pipe_client **_rpccli)
3375 TALLOC_CTX *frame = talloc_stackframe();
3376 struct rpc_pipe_client *rpccli;
3377 struct netlogon_creds_cli_lck *lck;
3380 status = netlogon_creds_cli_lck(
3381 netlogon_creds, NETLOGON_CREDS_CLI_LCK_EXCLUSIVE,
3383 if (!NT_STATUS_IS_OK(status)) {
3384 DBG_WARNING("netlogon_creds_cli_lck returned %s\n",
3390 status = cli_rpc_pipe_open_bind_schannel(
3391 cli, table, transport, netlogon_creds, &rpccli);
3392 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
3393 netlogon_creds_cli_delete_lck(netlogon_creds);
3395 if (!NT_STATUS_IS_OK(status)) {
3396 DBG_DEBUG("cli_rpc_pipe_open_bind_schannel failed: %s\n",
3402 if (ndr_syntax_id_equal(&table->syntax_id,
3403 &ndr_table_netlogon.syntax_id)) {
3404 status = netlogon_creds_cli_check(netlogon_creds,
3405 rpccli->binding_handle,
3407 if (!NT_STATUS_IS_OK(status)) {
3408 DEBUG(0, ("netlogon_creds_cli_check failed with %s\n",
3409 nt_errstr(status)));
3415 DBG_DEBUG("opened pipe %s to machine %s with key %s "
3416 "and bound using schannel.\n",
3417 table->name, rpccli->desthost,
3418 netlogon_creds_cli_debug_string(netlogon_creds, lck));
3423 return NT_STATUS_OK;
3426 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3427 struct rpc_pipe_client *cli,
3428 DATA_BLOB *session_key)
3431 struct pipe_auth_data *a;
3432 struct gensec_security *gensec_security;
3433 DATA_BLOB sk = data_blob_null;
3434 bool make_dup = false;
3436 if (!session_key || !cli) {
3437 return NT_STATUS_INVALID_PARAMETER;
3443 return NT_STATUS_INVALID_PARAMETER;
3446 switch (cli->auth->auth_type) {
3447 case DCERPC_AUTH_TYPE_NONE:
3448 sk = data_blob_const(a->transport_session_key.data,
3449 a->transport_session_key.length);
3453 gensec_security = a->auth_ctx;
3454 status = gensec_session_key(gensec_security, mem_ctx, &sk);
3455 if (!NT_STATUS_IS_OK(status)) {
3463 return NT_STATUS_NO_USER_SESSION_KEY;
3467 *session_key = data_blob_dup_talloc(mem_ctx, sk);
3472 return NT_STATUS_OK;