2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client routines
4 * Largely rewritten by Jeremy Allison 2005.
5 * Heavily modified by Simo Sorce 2010.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "librpc/gen_ndr/cli_epmapper.h"
23 #include "../librpc/gen_ndr/ndr_schannel.h"
24 #include "../librpc/gen_ndr/ndr_dssetup.h"
25 #include "../librpc/gen_ndr/ndr_netlogon.h"
26 #include "../libcli/auth/schannel.h"
27 #include "../libcli/auth/spnego.h"
29 #include "../libcli/auth/ntlmssp.h"
30 #include "ntlmssp_wrap.h"
31 #include "rpc_client/cli_netlogon.h"
32 #include "librpc/gen_ndr/ndr_dcerpc.h"
33 #include "librpc/rpc/dcerpc.h"
34 #include "librpc/rpc/dcerpc_gssapi.h"
35 #include "librpc/rpc/dcerpc_spnego.h"
38 #define DBGC_CLASS DBGC_RPC_CLI
40 /********************************************************************
41 Pipe description for a DEBUG
42 ********************************************************************/
43 static const char *rpccli_pipe_txt(TALLOC_CTX *mem_ctx,
44 struct rpc_pipe_client *cli)
46 char *result = talloc_asprintf(mem_ctx, "host %s", cli->desthost);
53 /********************************************************************
55 ********************************************************************/
57 static uint32 get_rpc_call_id(void)
59 static uint32 call_id = 0;
63 /*******************************************************************
64 Use SMBreadX to get rest of one fragment's worth of rpc data.
65 Reads the whole size or give an error message
66 ********************************************************************/
68 struct rpc_read_state {
69 struct event_context *ev;
70 struct rpc_cli_transport *transport;
76 static void rpc_read_done(struct tevent_req *subreq);
78 static struct tevent_req *rpc_read_send(TALLOC_CTX *mem_ctx,
79 struct event_context *ev,
80 struct rpc_cli_transport *transport,
81 uint8_t *data, size_t size)
83 struct tevent_req *req, *subreq;
84 struct rpc_read_state *state;
86 req = tevent_req_create(mem_ctx, &state, struct rpc_read_state);
91 state->transport = transport;
96 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size));
98 subreq = transport->read_send(state, ev, (uint8_t *)data, size,
100 if (subreq == NULL) {
103 tevent_req_set_callback(subreq, rpc_read_done, req);
111 static void rpc_read_done(struct tevent_req *subreq)
113 struct tevent_req *req = tevent_req_callback_data(
114 subreq, struct tevent_req);
115 struct rpc_read_state *state = tevent_req_data(
116 req, struct rpc_read_state);
120 status = state->transport->read_recv(subreq, &received);
122 if (!NT_STATUS_IS_OK(status)) {
123 tevent_req_nterror(req, status);
127 state->num_read += received;
128 if (state->num_read == state->size) {
129 tevent_req_done(req);
133 subreq = state->transport->read_send(state, state->ev,
134 state->data + state->num_read,
135 state->size - state->num_read,
136 state->transport->priv);
137 if (tevent_req_nomem(subreq, req)) {
140 tevent_req_set_callback(subreq, rpc_read_done, req);
143 static NTSTATUS rpc_read_recv(struct tevent_req *req)
145 return tevent_req_simple_recv_ntstatus(req);
148 struct rpc_write_state {
149 struct event_context *ev;
150 struct rpc_cli_transport *transport;
156 static void rpc_write_done(struct tevent_req *subreq);
158 static struct tevent_req *rpc_write_send(TALLOC_CTX *mem_ctx,
159 struct event_context *ev,
160 struct rpc_cli_transport *transport,
161 const uint8_t *data, size_t size)
163 struct tevent_req *req, *subreq;
164 struct rpc_write_state *state;
166 req = tevent_req_create(mem_ctx, &state, struct rpc_write_state);
171 state->transport = transport;
174 state->num_written = 0;
176 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size));
178 subreq = transport->write_send(state, ev, data, size, transport->priv);
179 if (subreq == NULL) {
182 tevent_req_set_callback(subreq, rpc_write_done, req);
189 static void rpc_write_done(struct tevent_req *subreq)
191 struct tevent_req *req = tevent_req_callback_data(
192 subreq, struct tevent_req);
193 struct rpc_write_state *state = tevent_req_data(
194 req, struct rpc_write_state);
198 status = state->transport->write_recv(subreq, &written);
200 if (!NT_STATUS_IS_OK(status)) {
201 tevent_req_nterror(req, status);
205 state->num_written += written;
207 if (state->num_written == state->size) {
208 tevent_req_done(req);
212 subreq = state->transport->write_send(state, state->ev,
213 state->data + state->num_written,
214 state->size - state->num_written,
215 state->transport->priv);
216 if (tevent_req_nomem(subreq, req)) {
219 tevent_req_set_callback(subreq, rpc_write_done, req);
222 static NTSTATUS rpc_write_recv(struct tevent_req *req)
224 return tevent_req_simple_recv_ntstatus(req);
228 /****************************************************************************
229 Try and get a PDU's worth of data from current_pdu. If not, then read more
231 ****************************************************************************/
233 struct get_complete_frag_state {
234 struct event_context *ev;
235 struct rpc_pipe_client *cli;
240 static void get_complete_frag_got_header(struct tevent_req *subreq);
241 static void get_complete_frag_got_rest(struct tevent_req *subreq);
243 static struct tevent_req *get_complete_frag_send(TALLOC_CTX *mem_ctx,
244 struct event_context *ev,
245 struct rpc_pipe_client *cli,
248 struct tevent_req *req, *subreq;
249 struct get_complete_frag_state *state;
253 req = tevent_req_create(mem_ctx, &state,
254 struct get_complete_frag_state);
260 state->frag_len = RPC_HEADER_LEN;
263 received = pdu->length;
264 if (received < RPC_HEADER_LEN) {
265 if (!data_blob_realloc(mem_ctx, pdu, RPC_HEADER_LEN)) {
266 status = NT_STATUS_NO_MEMORY;
269 subreq = rpc_read_send(state, state->ev,
270 state->cli->transport,
271 pdu->data + received,
272 RPC_HEADER_LEN - received);
273 if (subreq == NULL) {
274 status = NT_STATUS_NO_MEMORY;
277 tevent_req_set_callback(subreq, get_complete_frag_got_header,
282 state->frag_len = dcerpc_get_frag_length(pdu);
285 * Ensure we have frag_len bytes of data.
287 if (received < state->frag_len) {
288 if (!data_blob_realloc(NULL, pdu, state->frag_len)) {
289 status = NT_STATUS_NO_MEMORY;
292 subreq = rpc_read_send(state, state->ev,
293 state->cli->transport,
294 pdu->data + received,
295 state->frag_len - received);
296 if (subreq == NULL) {
297 status = NT_STATUS_NO_MEMORY;
300 tevent_req_set_callback(subreq, get_complete_frag_got_rest,
305 status = NT_STATUS_OK;
307 if (NT_STATUS_IS_OK(status)) {
308 tevent_req_done(req);
310 tevent_req_nterror(req, status);
312 return tevent_req_post(req, ev);
315 static void get_complete_frag_got_header(struct tevent_req *subreq)
317 struct tevent_req *req = tevent_req_callback_data(
318 subreq, struct tevent_req);
319 struct get_complete_frag_state *state = tevent_req_data(
320 req, struct get_complete_frag_state);
323 status = rpc_read_recv(subreq);
325 if (!NT_STATUS_IS_OK(status)) {
326 tevent_req_nterror(req, status);
330 state->frag_len = dcerpc_get_frag_length(state->pdu);
332 if (!data_blob_realloc(NULL, state->pdu, state->frag_len)) {
333 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
338 * We're here in this piece of code because we've read exactly
339 * RPC_HEADER_LEN bytes into state->pdu.
342 subreq = rpc_read_send(state, state->ev, state->cli->transport,
343 state->pdu->data + RPC_HEADER_LEN,
344 state->frag_len - RPC_HEADER_LEN);
345 if (tevent_req_nomem(subreq, req)) {
348 tevent_req_set_callback(subreq, get_complete_frag_got_rest, req);
351 static void get_complete_frag_got_rest(struct tevent_req *subreq)
353 struct tevent_req *req = tevent_req_callback_data(
354 subreq, struct tevent_req);
357 status = rpc_read_recv(subreq);
359 if (!NT_STATUS_IS_OK(status)) {
360 tevent_req_nterror(req, status);
363 tevent_req_done(req);
366 static NTSTATUS get_complete_frag_recv(struct tevent_req *req)
368 return tevent_req_simple_recv_ntstatus(req);
371 /****************************************************************************
372 Do basic authentication checks on an incoming pdu.
373 ****************************************************************************/
375 static NTSTATUS cli_pipe_validate_current_pdu(TALLOC_CTX *mem_ctx,
376 struct rpc_pipe_client *cli,
377 struct ncacn_packet *pkt,
379 uint8_t expected_pkt_type,
381 DATA_BLOB *reply_pdu)
383 struct dcerpc_response *r;
384 NTSTATUS ret = NT_STATUS_OK;
388 * Point the return values at the real data including the RPC
389 * header. Just in case the caller wants it.
393 /* Ensure we have the correct type. */
394 switch (pkt->ptype) {
395 case DCERPC_PKT_ALTER_RESP:
396 case DCERPC_PKT_BIND_ACK:
398 /* Client code never receives this kind of packets */
402 case DCERPC_PKT_RESPONSE:
404 r = &pkt->u.response;
406 /* Here's where we deal with incoming sign/seal. */
407 ret = dcerpc_check_auth(cli->auth, pkt,
408 &r->stub_and_verifier,
409 DCERPC_RESPONSE_LENGTH,
411 if (!NT_STATUS_IS_OK(ret)) {
415 if (pkt->frag_length < DCERPC_RESPONSE_LENGTH + pad_len) {
416 return NT_STATUS_BUFFER_TOO_SMALL;
419 /* Point the return values at the NDR data. */
420 rdata->data = r->stub_and_verifier.data;
422 if (pkt->auth_length) {
423 /* We've already done integer wrap tests in
424 * dcerpc_check_auth(). */
425 rdata->length = r->stub_and_verifier.length
427 - DCERPC_AUTH_TRAILER_LENGTH
430 rdata->length = r->stub_and_verifier.length;
433 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
434 (long unsigned int)pdu->length,
435 (long unsigned int)rdata->length,
436 (unsigned int)pad_len));
439 * If this is the first reply, and the allocation hint is
440 * reasonable, try and set up the reply_pdu DATA_BLOB to the
444 if ((reply_pdu->length == 0) &&
445 r->alloc_hint && (r->alloc_hint < 15*1024*1024)) {
446 if (!data_blob_realloc(mem_ctx, reply_pdu,
448 DEBUG(0, ("reply alloc hint %d too "
449 "large to allocate\n",
450 (int)r->alloc_hint));
451 return NT_STATUS_NO_MEMORY;
457 case DCERPC_PKT_BIND_NAK:
458 DEBUG(1, (__location__ ": Bind NACK received from %s!\n",
459 rpccli_pipe_txt(talloc_tos(), cli)));
460 /* Use this for now... */
461 return NT_STATUS_NETWORK_ACCESS_DENIED;
463 case DCERPC_PKT_FAULT:
465 DEBUG(1, (__location__ ": RPC fault code %s received "
467 dcerpc_errstr(talloc_tos(),
468 pkt->u.fault.status),
469 rpccli_pipe_txt(talloc_tos(), cli)));
471 if (NT_STATUS_IS_OK(NT_STATUS(pkt->u.fault.status))) {
472 return NT_STATUS_UNSUCCESSFUL;
474 return NT_STATUS(pkt->u.fault.status);
478 DEBUG(0, (__location__ "Unknown packet type %u received "
480 (unsigned int)pkt->ptype,
481 rpccli_pipe_txt(talloc_tos(), cli)));
482 return NT_STATUS_INVALID_INFO_CLASS;
485 if (pkt->ptype != expected_pkt_type) {
486 DEBUG(3, (__location__ ": Connection to %s got an unexpected "
487 "RPC packet type - %u, not %u\n",
488 rpccli_pipe_txt(talloc_tos(), cli),
489 pkt->ptype, expected_pkt_type));
490 return NT_STATUS_INVALID_INFO_CLASS;
493 /* Do this just before return - we don't want to modify any rpc header
494 data before now as we may have needed to do cryptographic actions on
497 if ((pkt->ptype == DCERPC_PKT_BIND_ACK) &&
498 !(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
499 DEBUG(5, (__location__ ": bug in server (AS/U?), setting "
500 "fragment first/last ON.\n"));
501 pkt->pfc_flags |= DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
507 /****************************************************************************
508 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
509 ****************************************************************************/
511 struct cli_api_pipe_state {
512 struct event_context *ev;
513 struct rpc_cli_transport *transport;
518 static void cli_api_pipe_trans_done(struct tevent_req *subreq);
519 static void cli_api_pipe_write_done(struct tevent_req *subreq);
520 static void cli_api_pipe_read_done(struct tevent_req *subreq);
522 static struct tevent_req *cli_api_pipe_send(TALLOC_CTX *mem_ctx,
523 struct event_context *ev,
524 struct rpc_cli_transport *transport,
525 uint8_t *data, size_t data_len,
526 uint32_t max_rdata_len)
528 struct tevent_req *req, *subreq;
529 struct cli_api_pipe_state *state;
532 req = tevent_req_create(mem_ctx, &state, struct cli_api_pipe_state);
537 state->transport = transport;
539 if (max_rdata_len < RPC_HEADER_LEN) {
541 * For a RPC reply we always need at least RPC_HEADER_LEN
542 * bytes. We check this here because we will receive
543 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
545 status = NT_STATUS_INVALID_PARAMETER;
549 if (transport->trans_send != NULL) {
550 subreq = transport->trans_send(state, ev, data, data_len,
551 max_rdata_len, transport->priv);
552 if (subreq == NULL) {
555 tevent_req_set_callback(subreq, cli_api_pipe_trans_done, req);
560 * If the transport does not provide a "trans" routine, i.e. for
561 * example the ncacn_ip_tcp transport, do the write/read step here.
564 subreq = rpc_write_send(state, ev, transport, data, data_len);
565 if (subreq == NULL) {
568 tevent_req_set_callback(subreq, cli_api_pipe_write_done, req);
572 tevent_req_nterror(req, status);
573 return tevent_req_post(req, ev);
579 static void cli_api_pipe_trans_done(struct tevent_req *subreq)
581 struct tevent_req *req = tevent_req_callback_data(
582 subreq, struct tevent_req);
583 struct cli_api_pipe_state *state = tevent_req_data(
584 req, struct cli_api_pipe_state);
587 status = state->transport->trans_recv(subreq, state, &state->rdata,
590 if (!NT_STATUS_IS_OK(status)) {
591 tevent_req_nterror(req, status);
594 tevent_req_done(req);
597 static void cli_api_pipe_write_done(struct tevent_req *subreq)
599 struct tevent_req *req = tevent_req_callback_data(
600 subreq, struct tevent_req);
601 struct cli_api_pipe_state *state = tevent_req_data(
602 req, struct cli_api_pipe_state);
605 status = rpc_write_recv(subreq);
607 if (!NT_STATUS_IS_OK(status)) {
608 tevent_req_nterror(req, status);
612 state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN);
613 if (tevent_req_nomem(state->rdata, req)) {
618 * We don't need to use rpc_read_send here, the upper layer will cope
619 * with a short read, transport->trans_send could also return less
620 * than state->max_rdata_len.
622 subreq = state->transport->read_send(state, state->ev, state->rdata,
624 state->transport->priv);
625 if (tevent_req_nomem(subreq, req)) {
628 tevent_req_set_callback(subreq, cli_api_pipe_read_done, req);
631 static void cli_api_pipe_read_done(struct tevent_req *subreq)
633 struct tevent_req *req = tevent_req_callback_data(
634 subreq, struct tevent_req);
635 struct cli_api_pipe_state *state = tevent_req_data(
636 req, struct cli_api_pipe_state);
640 status = state->transport->read_recv(subreq, &received);
642 if (!NT_STATUS_IS_OK(status)) {
643 tevent_req_nterror(req, status);
646 state->rdata_len = received;
647 tevent_req_done(req);
650 static NTSTATUS cli_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
651 uint8_t **prdata, uint32_t *prdata_len)
653 struct cli_api_pipe_state *state = tevent_req_data(
654 req, struct cli_api_pipe_state);
657 if (tevent_req_is_nterror(req, &status)) {
661 *prdata = talloc_move(mem_ctx, &state->rdata);
662 *prdata_len = state->rdata_len;
666 /****************************************************************************
667 Send data on an rpc pipe via trans. The data must be the last
668 pdu fragment of an NDR data stream.
670 Receive response data from an rpc pipe, which may be large...
672 Read the first fragment: unfortunately have to use SMBtrans for the first
673 bit, then SMBreadX for subsequent bits.
675 If first fragment received also wasn't the last fragment, continue
676 getting fragments until we _do_ receive the last fragment.
678 Request/Response PDU's look like the following...
680 |<------------------PDU len----------------------------------------------->|
681 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
683 +------------+-----------------+-------------+---------------+-------------+
684 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
685 +------------+-----------------+-------------+---------------+-------------+
687 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
688 signing & sealing being negotiated.
690 ****************************************************************************/
692 struct rpc_api_pipe_state {
693 struct event_context *ev;
694 struct rpc_pipe_client *cli;
695 uint8_t expected_pkt_type;
697 DATA_BLOB incoming_frag;
698 struct ncacn_packet *pkt;
702 size_t reply_pdu_offset;
706 static void rpc_api_pipe_trans_done(struct tevent_req *subreq);
707 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq);
709 static struct tevent_req *rpc_api_pipe_send(TALLOC_CTX *mem_ctx,
710 struct event_context *ev,
711 struct rpc_pipe_client *cli,
712 DATA_BLOB *data, /* Outgoing PDU */
713 uint8_t expected_pkt_type)
715 struct tevent_req *req, *subreq;
716 struct rpc_api_pipe_state *state;
717 uint16_t max_recv_frag;
720 req = tevent_req_create(mem_ctx, &state, struct rpc_api_pipe_state);
726 state->expected_pkt_type = expected_pkt_type;
727 state->incoming_frag = data_blob_null;
728 state->reply_pdu = data_blob_null;
729 state->reply_pdu_offset = 0;
730 state->endianess = DCERPC_DREP_LE;
733 * Ensure we're not sending too much.
735 if (data->length > cli->max_xmit_frag) {
736 status = NT_STATUS_INVALID_PARAMETER;
740 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli)));
742 /* get the header first, then fetch the rest once we have
743 * the frag_length available */
744 max_recv_frag = RPC_HEADER_LEN;
746 subreq = cli_api_pipe_send(state, ev, cli->transport,
747 data->data, data->length, max_recv_frag);
748 if (subreq == NULL) {
751 tevent_req_set_callback(subreq, rpc_api_pipe_trans_done, req);
755 tevent_req_nterror(req, status);
756 return tevent_req_post(req, ev);
762 static void rpc_api_pipe_trans_done(struct tevent_req *subreq)
764 struct tevent_req *req = tevent_req_callback_data(
765 subreq, struct tevent_req);
766 struct rpc_api_pipe_state *state = tevent_req_data(
767 req, struct rpc_api_pipe_state);
769 uint8_t *rdata = NULL;
770 uint32_t rdata_len = 0;
772 status = cli_api_pipe_recv(subreq, state, &rdata, &rdata_len);
774 if (!NT_STATUS_IS_OK(status)) {
775 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status)));
776 tevent_req_nterror(req, status);
781 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
782 rpccli_pipe_txt(talloc_tos(), state->cli)));
783 tevent_req_done(req);
788 * Move data on state->incoming_frag.
790 state->incoming_frag.data = talloc_move(state, &rdata);
791 state->incoming_frag.length = rdata_len;
792 if (!state->incoming_frag.data) {
793 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
797 /* Ensure we have enough data for a pdu. */
798 subreq = get_complete_frag_send(state, state->ev, state->cli,
799 &state->incoming_frag);
800 if (tevent_req_nomem(subreq, req)) {
803 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
806 static void rpc_api_pipe_got_pdu(struct tevent_req *subreq)
808 struct tevent_req *req = tevent_req_callback_data(
809 subreq, struct tevent_req);
810 struct rpc_api_pipe_state *state = tevent_req_data(
811 req, struct rpc_api_pipe_state);
813 DATA_BLOB rdata = data_blob_null;
815 status = get_complete_frag_recv(subreq);
817 if (!NT_STATUS_IS_OK(status)) {
818 DEBUG(5, ("get_complete_frag failed: %s\n",
820 tevent_req_nterror(req, status);
824 state->pkt = talloc(state, struct ncacn_packet);
826 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
830 status = dcerpc_pull_ncacn_packet(state->pkt,
831 &state->incoming_frag,
834 if (!NT_STATUS_IS_OK(status)) {
835 tevent_req_nterror(req, status);
839 if (state->incoming_frag.length != state->pkt->frag_length) {
840 DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
841 (unsigned int)state->incoming_frag.length,
842 (unsigned int)state->pkt->frag_length));
843 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
847 status = cli_pipe_validate_current_pdu(state,
848 state->cli, state->pkt,
849 &state->incoming_frag,
850 state->expected_pkt_type,
854 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
855 (unsigned)state->incoming_frag.length,
856 (unsigned)state->reply_pdu_offset,
859 if (!NT_STATUS_IS_OK(status)) {
860 tevent_req_nterror(req, status);
864 if ((state->pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)
865 && (state->pkt->drep[0] != DCERPC_DREP_LE)) {
867 * Set the data type correctly for big-endian data on the
870 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
872 rpccli_pipe_txt(talloc_tos(), state->cli)));
873 state->endianess = 0x00; /* BIG ENDIAN */
876 * Check endianness on subsequent packets.
878 if (state->endianess != state->pkt->drep[0]) {
879 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
881 state->endianess?"little":"big",
882 state->pkt->drep[0]?"little":"big"));
883 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
887 /* Now copy the data portion out of the pdu into rbuf. */
888 if (state->reply_pdu.length < state->reply_pdu_offset + rdata.length) {
889 if (!data_blob_realloc(NULL, &state->reply_pdu,
890 state->reply_pdu_offset + rdata.length)) {
891 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
896 memcpy(state->reply_pdu.data + state->reply_pdu_offset,
897 rdata.data, rdata.length);
898 state->reply_pdu_offset += rdata.length;
900 /* reset state->incoming_frag, there is no need to free it,
901 * it will be reallocated to the right size the next time
903 state->incoming_frag.length = 0;
905 if (state->pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
906 /* make sure the pdu length is right now that we
907 * have all the data available (alloc hint may
908 * have allocated more than was actually used) */
909 state->reply_pdu.length = state->reply_pdu_offset;
910 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
911 rpccli_pipe_txt(talloc_tos(), state->cli),
912 (unsigned)state->reply_pdu.length));
913 tevent_req_done(req);
917 subreq = get_complete_frag_send(state, state->ev, state->cli,
918 &state->incoming_frag);
919 if (tevent_req_nomem(subreq, req)) {
922 tevent_req_set_callback(subreq, rpc_api_pipe_got_pdu, req);
925 static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
926 struct ncacn_packet **pkt,
927 DATA_BLOB *reply_pdu)
929 struct rpc_api_pipe_state *state = tevent_req_data(
930 req, struct rpc_api_pipe_state);
933 if (tevent_req_is_nterror(req, &status)) {
937 /* return data to caller and assign it ownership of memory */
939 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
940 reply_pdu->length = state->reply_pdu.length;
941 state->reply_pdu.length = 0;
943 data_blob_free(&state->reply_pdu);
947 *pkt = talloc_steal(mem_ctx, state->pkt);
953 /*******************************************************************
954 Creates spnego auth bind.
955 ********************************************************************/
957 static NTSTATUS create_spnego_auth_bind_req(TALLOC_CTX *mem_ctx,
958 struct pipe_auth_data *auth,
959 DATA_BLOB *auth_token)
961 DATA_BLOB in_token = data_blob_null;
964 /* Negotiate the initial auth token */
965 status = spnego_get_client_auth_token(mem_ctx,
966 auth->a_u.spnego_state,
967 &in_token, auth_token);
968 if (!NT_STATUS_IS_OK(status)) {
972 DEBUG(5, ("Created GSS Authentication Token:\n"));
973 dump_data(5, auth_token->data, auth_token->length);
978 /*******************************************************************
979 Creates krb5 auth bind.
980 ********************************************************************/
982 static NTSTATUS create_gssapi_auth_bind_req(TALLOC_CTX *mem_ctx,
983 struct pipe_auth_data *auth,
984 DATA_BLOB *auth_token)
986 DATA_BLOB in_token = data_blob_null;
989 /* Negotiate the initial auth token */
990 status = gse_get_client_auth_token(mem_ctx,
991 auth->a_u.gssapi_state,
994 if (!NT_STATUS_IS_OK(status)) {
998 DEBUG(5, ("Created GSS Authentication Token:\n"));
999 dump_data(5, auth_token->data, auth_token->length);
1001 return NT_STATUS_OK;
1004 /*******************************************************************
1005 Creates NTLMSSP auth bind.
1006 ********************************************************************/
1008 static NTSTATUS create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1009 DATA_BLOB *auth_token)
1012 DATA_BLOB null_blob = data_blob_null;
1014 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1015 status = auth_ntlmssp_update(cli->auth->a_u.auth_ntlmssp_state,
1016 null_blob, auth_token);
1018 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1019 data_blob_free(auth_token);
1023 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1024 dump_data(5, auth_token->data, auth_token->length);
1026 return NT_STATUS_OK;
1029 /*******************************************************************
1030 Creates schannel auth bind.
1031 ********************************************************************/
1033 static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
1034 DATA_BLOB *auth_token)
1037 struct NL_AUTH_MESSAGE r;
1039 /* Use lp_workgroup() if domain not specified */
1041 if (!cli->auth->domain || !cli->auth->domain[0]) {
1042 cli->auth->domain = talloc_strdup(cli, lp_workgroup());
1043 if (cli->auth->domain == NULL) {
1044 return NT_STATUS_NO_MEMORY;
1049 * Now marshall the data into the auth parse_struct.
1052 r.MessageType = NL_NEGOTIATE_REQUEST;
1053 r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
1054 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
1055 r.oem_netbios_domain.a = cli->auth->domain;
1056 r.oem_netbios_computer.a = global_myname();
1058 status = dcerpc_push_schannel_bind(cli, &r, auth_token);
1059 if (!NT_STATUS_IS_OK(status)) {
1063 return NT_STATUS_OK;
1066 /*******************************************************************
1067 Creates the internals of a DCE/RPC bind request or alter context PDU.
1068 ********************************************************************/
1070 static NTSTATUS create_bind_or_alt_ctx_internal(TALLOC_CTX *mem_ctx,
1071 enum dcerpc_pkt_type ptype,
1073 const struct ndr_syntax_id *abstract,
1074 const struct ndr_syntax_id *transfer,
1075 const DATA_BLOB *auth_info,
1078 uint16 auth_len = auth_info->length;
1080 union dcerpc_payload u;
1081 struct dcerpc_ctx_list ctx_list;
1084 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1087 ctx_list.context_id = 0;
1088 ctx_list.num_transfer_syntaxes = 1;
1089 ctx_list.abstract_syntax = *abstract;
1090 ctx_list.transfer_syntaxes = (struct ndr_syntax_id *)discard_const(transfer);
1092 u.bind.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
1093 u.bind.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
1094 u.bind.assoc_group_id = 0x0;
1095 u.bind.num_contexts = 1;
1096 u.bind.ctx_list = &ctx_list;
1097 u.bind.auth_info = *auth_info;
1099 status = dcerpc_push_ncacn_packet(mem_ctx,
1101 DCERPC_PFC_FLAG_FIRST |
1102 DCERPC_PFC_FLAG_LAST,
1107 if (!NT_STATUS_IS_OK(status)) {
1108 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1112 return NT_STATUS_OK;
1115 /*******************************************************************
1116 Creates a DCE/RPC bind request.
1117 ********************************************************************/
1119 static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx,
1120 struct rpc_pipe_client *cli,
1121 struct pipe_auth_data *auth,
1123 const struct ndr_syntax_id *abstract,
1124 const struct ndr_syntax_id *transfer,
1127 DATA_BLOB auth_token = data_blob_null;
1128 DATA_BLOB auth_info = data_blob_null;
1129 NTSTATUS ret = NT_STATUS_OK;
1131 switch (auth->auth_type) {
1132 case DCERPC_AUTH_TYPE_SCHANNEL:
1133 ret = create_schannel_auth_rpc_bind_req(cli, &auth_token);
1134 if (!NT_STATUS_IS_OK(ret)) {
1139 case DCERPC_AUTH_TYPE_NTLMSSP:
1140 ret = create_ntlmssp_auth_rpc_bind_req(cli, &auth_token);
1141 if (!NT_STATUS_IS_OK(ret)) {
1146 case DCERPC_AUTH_TYPE_SPNEGO:
1147 ret = create_spnego_auth_bind_req(cli, auth, &auth_token);
1148 if (!NT_STATUS_IS_OK(ret)) {
1153 case DCERPC_AUTH_TYPE_KRB5:
1154 ret = create_gssapi_auth_bind_req(mem_ctx, auth, &auth_token);
1155 if (!NT_STATUS_IS_OK(ret)) {
1160 case DCERPC_AUTH_TYPE_NONE:
1164 /* "Can't" happen. */
1165 return NT_STATUS_INVALID_INFO_CLASS;
1168 if (auth_token.length != 0) {
1169 ret = dcerpc_push_dcerpc_auth(cli,
1172 0, /* auth_pad_length */
1173 1, /* auth_context_id */
1176 if (!NT_STATUS_IS_OK(ret)) {
1179 data_blob_free(&auth_token);
1182 ret = create_bind_or_alt_ctx_internal(mem_ctx,
1192 /*******************************************************************
1194 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1195 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1196 and deals with signing/sealing details.
1197 ********************************************************************/
1199 struct rpc_api_pipe_req_state {
1200 struct event_context *ev;
1201 struct rpc_pipe_client *cli;
1204 DATA_BLOB *req_data;
1205 uint32_t req_data_sent;
1207 DATA_BLOB reply_pdu;
1210 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq);
1211 static void rpc_api_pipe_req_done(struct tevent_req *subreq);
1212 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1213 bool *is_last_frag);
1215 struct tevent_req *rpc_api_pipe_req_send(TALLOC_CTX *mem_ctx,
1216 struct event_context *ev,
1217 struct rpc_pipe_client *cli,
1219 DATA_BLOB *req_data)
1221 struct tevent_req *req, *subreq;
1222 struct rpc_api_pipe_req_state *state;
1226 req = tevent_req_create(mem_ctx, &state,
1227 struct rpc_api_pipe_req_state);
1233 state->op_num = op_num;
1234 state->req_data = req_data;
1235 state->req_data_sent = 0;
1236 state->call_id = get_rpc_call_id();
1237 state->reply_pdu = data_blob_null;
1238 state->rpc_out = data_blob_null;
1240 if (cli->max_xmit_frag < DCERPC_REQUEST_LENGTH
1241 + RPC_MAX_SIGN_SIZE) {
1242 /* Server is screwed up ! */
1243 status = NT_STATUS_INVALID_PARAMETER;
1247 status = prepare_next_frag(state, &is_last_frag);
1248 if (!NT_STATUS_IS_OK(status)) {
1253 subreq = rpc_api_pipe_send(state, ev, state->cli,
1255 DCERPC_PKT_RESPONSE);
1256 if (subreq == NULL) {
1259 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1261 subreq = rpc_write_send(state, ev, cli->transport,
1262 state->rpc_out.data,
1263 state->rpc_out.length);
1264 if (subreq == NULL) {
1267 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1273 tevent_req_nterror(req, status);
1274 return tevent_req_post(req, ev);
1280 static NTSTATUS prepare_next_frag(struct rpc_api_pipe_req_state *state,
1283 size_t data_sent_thistime;
1290 union dcerpc_payload u;
1292 data_left = state->req_data->length - state->req_data_sent;
1294 status = dcerpc_guess_sizes(state->cli->auth,
1295 DCERPC_REQUEST_LENGTH, data_left,
1296 state->cli->max_xmit_frag,
1297 CLIENT_NDR_PADDING_SIZE,
1298 &data_sent_thistime,
1299 &frag_len, &auth_len, &pad_len);
1300 if (!NT_STATUS_IS_OK(status)) {
1304 if (state->req_data_sent == 0) {
1305 flags = DCERPC_PFC_FLAG_FIRST;
1308 if (data_sent_thistime == data_left) {
1309 flags |= DCERPC_PFC_FLAG_LAST;
1312 data_blob_free(&state->rpc_out);
1314 ZERO_STRUCT(u.request);
1316 u.request.alloc_hint = state->req_data->length;
1317 u.request.context_id = 0;
1318 u.request.opnum = state->op_num;
1320 status = dcerpc_push_ncacn_packet(state,
1327 if (!NT_STATUS_IS_OK(status)) {
1331 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1332 * compute it right for requests because the auth trailer is missing
1334 dcerpc_set_frag_length(&state->rpc_out, frag_len);
1336 /* Copy in the data. */
1337 if (!data_blob_append(NULL, &state->rpc_out,
1338 state->req_data->data + state->req_data_sent,
1339 data_sent_thistime)) {
1340 return NT_STATUS_NO_MEMORY;
1343 switch (state->cli->auth->auth_level) {
1344 case DCERPC_AUTH_LEVEL_NONE:
1345 case DCERPC_AUTH_LEVEL_CONNECT:
1346 case DCERPC_AUTH_LEVEL_PACKET:
1348 case DCERPC_AUTH_LEVEL_INTEGRITY:
1349 case DCERPC_AUTH_LEVEL_PRIVACY:
1350 status = dcerpc_add_auth_footer(state->cli->auth, pad_len,
1352 if (!NT_STATUS_IS_OK(status)) {
1357 return NT_STATUS_INVALID_PARAMETER;
1360 state->req_data_sent += data_sent_thistime;
1361 *is_last_frag = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
1366 static void rpc_api_pipe_req_write_done(struct tevent_req *subreq)
1368 struct tevent_req *req = tevent_req_callback_data(
1369 subreq, struct tevent_req);
1370 struct rpc_api_pipe_req_state *state = tevent_req_data(
1371 req, struct rpc_api_pipe_req_state);
1375 status = rpc_write_recv(subreq);
1376 TALLOC_FREE(subreq);
1377 if (!NT_STATUS_IS_OK(status)) {
1378 tevent_req_nterror(req, status);
1382 status = prepare_next_frag(state, &is_last_frag);
1383 if (!NT_STATUS_IS_OK(status)) {
1384 tevent_req_nterror(req, status);
1389 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1391 DCERPC_PKT_RESPONSE);
1392 if (tevent_req_nomem(subreq, req)) {
1395 tevent_req_set_callback(subreq, rpc_api_pipe_req_done, req);
1397 subreq = rpc_write_send(state, state->ev,
1398 state->cli->transport,
1399 state->rpc_out.data,
1400 state->rpc_out.length);
1401 if (tevent_req_nomem(subreq, req)) {
1404 tevent_req_set_callback(subreq, rpc_api_pipe_req_write_done,
1409 static void rpc_api_pipe_req_done(struct tevent_req *subreq)
1411 struct tevent_req *req = tevent_req_callback_data(
1412 subreq, struct tevent_req);
1413 struct rpc_api_pipe_req_state *state = tevent_req_data(
1414 req, struct rpc_api_pipe_req_state);
1417 status = rpc_api_pipe_recv(subreq, state, NULL, &state->reply_pdu);
1418 TALLOC_FREE(subreq);
1419 if (!NT_STATUS_IS_OK(status)) {
1420 tevent_req_nterror(req, status);
1423 tevent_req_done(req);
1426 NTSTATUS rpc_api_pipe_req_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
1427 DATA_BLOB *reply_pdu)
1429 struct rpc_api_pipe_req_state *state = tevent_req_data(
1430 req, struct rpc_api_pipe_req_state);
1433 if (tevent_req_is_nterror(req, &status)) {
1435 * We always have to initialize to reply pdu, even if there is
1436 * none. The rpccli_* caller routines expect this.
1438 *reply_pdu = data_blob_null;
1442 /* return data to caller and assign it ownership of memory */
1443 reply_pdu->data = talloc_move(mem_ctx, &state->reply_pdu.data);
1444 reply_pdu->length = state->reply_pdu.length;
1445 state->reply_pdu.length = 0;
1447 return NT_STATUS_OK;
1451 /****************************************************************************
1452 Set the handle state.
1453 ****************************************************************************/
1455 static bool rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
1456 const char *pipe_name, uint16 device_state)
1458 bool state_set = False;
1460 uint16 setup[2]; /* only need 2 uint16 setup parameters */
1461 char *rparam = NULL;
1463 uint32 rparam_len, rdata_len;
1465 if (pipe_name == NULL)
1468 DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
1469 cli->fnum, pipe_name, device_state));
1471 /* create parameters: device state */
1472 SSVAL(param, 0, device_state);
1474 /* create setup parameters. */
1476 setup[1] = cli->fnum; /* pipe file handle. got this from an SMBOpenX. */
1478 /* send the data on \PIPE\ */
1479 if (cli_api_pipe(cli->cli, "\\PIPE\\",
1480 setup, 2, 0, /* setup, length, max */
1481 param, 2, 0, /* param, length, max */
1482 NULL, 0, 1024, /* data, length, max */
1483 &rparam, &rparam_len, /* return param, length */
1484 &rdata, &rdata_len)) /* return data, length */
1486 DEBUG(5, ("Set Handle state: return OK\n"));
1497 /****************************************************************************
1498 Check the rpc bind acknowledge response.
1499 ****************************************************************************/
1501 static bool check_bind_response(const struct dcerpc_bind_ack *r,
1502 const struct ndr_syntax_id *transfer)
1504 struct dcerpc_ack_ctx ctx;
1506 if (r->secondary_address_size == 0) {
1507 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1510 if (r->num_results < 1 || !r->ctx_list) {
1514 ctx = r->ctx_list[0];
1516 /* check the transfer syntax */
1517 if ((ctx.syntax.if_version != transfer->if_version) ||
1518 (memcmp(&ctx.syntax.uuid, &transfer->uuid, sizeof(transfer->uuid)) !=0)) {
1519 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1523 if (r->num_results != 0x1 || ctx.result != 0) {
1524 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1525 r->num_results, ctx.reason));
1528 DEBUG(5,("check_bind_response: accepted!\n"));
1532 /*******************************************************************
1533 Creates a DCE/RPC bind authentication response.
1534 This is the packet that is sent back to the server once we
1535 have received a BIND-ACK, to finish the third leg of
1536 the authentication handshake.
1537 ********************************************************************/
1539 static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
1540 struct rpc_pipe_client *cli,
1542 enum dcerpc_AuthType auth_type,
1543 enum dcerpc_AuthLevel auth_level,
1544 DATA_BLOB *pauth_blob,
1548 union dcerpc_payload u;
1552 status = dcerpc_push_dcerpc_auth(mem_ctx,
1555 0, /* auth_pad_length */
1556 1, /* auth_context_id */
1558 &u.auth3.auth_info);
1559 if (!NT_STATUS_IS_OK(status)) {
1563 status = dcerpc_push_ncacn_packet(mem_ctx,
1565 DCERPC_PFC_FLAG_FIRST |
1566 DCERPC_PFC_FLAG_LAST,
1571 data_blob_free(&u.auth3.auth_info);
1572 if (!NT_STATUS_IS_OK(status)) {
1573 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1577 return NT_STATUS_OK;
1580 /*******************************************************************
1581 Creates a DCE/RPC bind alter context authentication request which
1582 may contain a spnego auth blobl
1583 ********************************************************************/
1585 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
1586 enum dcerpc_AuthType auth_type,
1587 enum dcerpc_AuthLevel auth_level,
1589 const struct ndr_syntax_id *abstract,
1590 const struct ndr_syntax_id *transfer,
1591 const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
1594 DATA_BLOB auth_info;
1597 status = dcerpc_push_dcerpc_auth(mem_ctx,
1600 0, /* auth_pad_length */
1601 1, /* auth_context_id */
1604 if (!NT_STATUS_IS_OK(status)) {
1608 status = create_bind_or_alt_ctx_internal(mem_ctx,
1615 data_blob_free(&auth_info);
1619 /****************************************************************************
1621 ****************************************************************************/
1623 struct rpc_pipe_bind_state {
1624 struct event_context *ev;
1625 struct rpc_pipe_client *cli;
1627 uint32_t rpc_call_id;
1630 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
1631 static void rpc_bind_auth3_write_done(struct tevent_req *subreq);
1632 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1633 struct rpc_pipe_bind_state *state,
1634 DATA_BLOB *credentials);
1635 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1636 struct rpc_pipe_bind_state *state,
1637 DATA_BLOB *credentials);
1639 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
1640 struct event_context *ev,
1641 struct rpc_pipe_client *cli,
1642 struct pipe_auth_data *auth)
1644 struct tevent_req *req, *subreq;
1645 struct rpc_pipe_bind_state *state;
1648 req = tevent_req_create(mem_ctx, &state, struct rpc_pipe_bind_state);
1653 DEBUG(5,("Bind RPC Pipe: %s auth_type %u(%u), auth_level %u\n",
1654 rpccli_pipe_txt(talloc_tos(), cli),
1655 (unsigned int)auth->auth_type,
1656 (unsigned int)auth->spnego_type,
1657 (unsigned int)auth->auth_level ));
1661 state->rpc_call_id = get_rpc_call_id();
1662 state->rpc_out = data_blob_null;
1664 cli->auth = talloc_move(cli, &auth);
1666 /* Marshall the outgoing data. */
1667 status = create_rpc_bind_req(state, cli,
1670 &cli->abstract_syntax,
1671 &cli->transfer_syntax,
1674 if (!NT_STATUS_IS_OK(status)) {
1678 subreq = rpc_api_pipe_send(state, ev, cli, &state->rpc_out,
1679 DCERPC_PKT_BIND_ACK);
1680 if (subreq == NULL) {
1683 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1687 tevent_req_nterror(req, status);
1688 return tevent_req_post(req, ev);
1694 static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
1696 struct tevent_req *req = tevent_req_callback_data(
1697 subreq, struct tevent_req);
1698 struct rpc_pipe_bind_state *state = tevent_req_data(
1699 req, struct rpc_pipe_bind_state);
1700 struct pipe_auth_data *pauth = state->cli->auth;
1701 DATA_BLOB reply_pdu;
1702 struct ncacn_packet *pkt;
1703 struct dcerpc_auth auth;
1704 DATA_BLOB auth_token = data_blob_null;
1707 status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu);
1708 TALLOC_FREE(subreq);
1709 if (!NT_STATUS_IS_OK(status)) {
1710 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1711 rpccli_pipe_txt(talloc_tos(), state->cli),
1712 nt_errstr(status)));
1713 tevent_req_nterror(req, status);
1717 if (!check_bind_response(&pkt->u.bind_ack, &state->cli->transfer_syntax)) {
1718 DEBUG(2, ("rpc_pipe_bind: check_bind_response failed.\n"));
1719 tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
1723 state->cli->max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1724 state->cli->max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1726 switch(pauth->auth_type) {
1728 case DCERPC_AUTH_TYPE_NONE:
1729 case DCERPC_AUTH_TYPE_SCHANNEL:
1730 /* Bind complete. */
1731 tevent_req_done(req);
1734 case DCERPC_AUTH_TYPE_NTLMSSP:
1735 case DCERPC_AUTH_TYPE_SPNEGO:
1736 case DCERPC_AUTH_TYPE_KRB5:
1737 /* Paranoid lenght checks */
1738 if (pkt->frag_length < DCERPC_AUTH_TRAILER_LENGTH
1739 + pkt->auth_length) {
1740 tevent_req_nterror(req,
1741 NT_STATUS_INFO_LENGTH_MISMATCH);
1744 /* get auth credentials */
1745 status = dcerpc_pull_dcerpc_auth(talloc_tos(),
1746 &pkt->u.bind_ack.auth_info,
1748 if (!NT_STATUS_IS_OK(status)) {
1749 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1750 nt_errstr(status)));
1751 tevent_req_nterror(req, status);
1761 * For authenticated binds we may need to do 3 or 4 leg binds.
1764 switch(pauth->auth_type) {
1766 case DCERPC_AUTH_TYPE_NONE:
1767 case DCERPC_AUTH_TYPE_SCHANNEL:
1768 /* Bind complete. */
1769 tevent_req_done(req);
1772 case DCERPC_AUTH_TYPE_NTLMSSP:
1773 status = auth_ntlmssp_update(pauth->a_u.auth_ntlmssp_state,
1774 auth.credentials, &auth_token);
1775 if (NT_STATUS_EQUAL(status,
1776 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1777 status = rpc_bind_next_send(req, state,
1779 } else if (NT_STATUS_IS_OK(status)) {
1780 status = rpc_bind_finish_send(req, state,
1785 case DCERPC_AUTH_TYPE_SPNEGO:
1786 status = spnego_get_client_auth_token(state,
1787 pauth->a_u.spnego_state,
1790 if (!NT_STATUS_IS_OK(status)) {
1793 if (auth_token.length == 0) {
1794 /* Bind complete. */
1795 tevent_req_done(req);
1798 if (spnego_require_more_processing(pauth->a_u.spnego_state)) {
1799 status = rpc_bind_next_send(req, state,
1802 status = rpc_bind_finish_send(req, state,
1807 case DCERPC_AUTH_TYPE_KRB5:
1808 status = gse_get_client_auth_token(state,
1809 pauth->a_u.gssapi_state,
1812 if (!NT_STATUS_IS_OK(status)) {
1816 if (gse_require_more_processing(pauth->a_u.gssapi_state)) {
1817 status = rpc_bind_next_send(req, state, &auth_token);
1819 status = rpc_bind_finish_send(req, state, &auth_token);
1827 if (!NT_STATUS_IS_OK(status)) {
1828 tevent_req_nterror(req, status);
1833 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u(%u)\n",
1834 (unsigned int)state->cli->auth->auth_type,
1835 (unsigned int)state->cli->auth->spnego_type));
1836 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1839 static void rpc_bind_auth3_write_done(struct tevent_req *subreq)
1841 struct tevent_req *req = tevent_req_callback_data(
1842 subreq, struct tevent_req);
1845 status = rpc_write_recv(subreq);
1846 TALLOC_FREE(subreq);
1847 if (!NT_STATUS_IS_OK(status)) {
1848 tevent_req_nterror(req, status);
1851 tevent_req_done(req);
1854 static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
1855 struct rpc_pipe_bind_state *state,
1856 DATA_BLOB *auth_token)
1858 struct pipe_auth_data *auth = state->cli->auth;
1859 struct tevent_req *subreq;
1862 /* Now prepare the alter context pdu. */
1863 data_blob_free(&state->rpc_out);
1865 status = create_rpc_alter_context(state,
1869 &state->cli->abstract_syntax,
1870 &state->cli->transfer_syntax,
1873 if (!NT_STATUS_IS_OK(status)) {
1877 subreq = rpc_api_pipe_send(state, state->ev, state->cli,
1878 &state->rpc_out, DCERPC_PKT_ALTER_RESP);
1879 if (subreq == NULL) {
1880 return NT_STATUS_NO_MEMORY;
1882 tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
1883 return NT_STATUS_OK;
1886 static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
1887 struct rpc_pipe_bind_state *state,
1888 DATA_BLOB *auth_token)
1890 struct pipe_auth_data *auth = state->cli->auth;
1891 struct tevent_req *subreq;
1894 /* Now prepare the auth3 context pdu. */
1895 data_blob_free(&state->rpc_out);
1897 status = create_rpc_bind_auth3(state, state->cli,
1903 if (!NT_STATUS_IS_OK(status)) {
1907 subreq = rpc_write_send(state, state->ev, state->cli->transport,
1908 state->rpc_out.data, state->rpc_out.length);
1909 if (subreq == NULL) {
1910 return NT_STATUS_NO_MEMORY;
1912 tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
1913 return NT_STATUS_OK;
1916 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
1918 return tevent_req_simple_recv_ntstatus(req);
1921 NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
1922 struct pipe_auth_data *auth)
1924 TALLOC_CTX *frame = talloc_stackframe();
1925 struct event_context *ev;
1926 struct tevent_req *req;
1927 NTSTATUS status = NT_STATUS_OK;
1929 ev = event_context_init(frame);
1931 status = NT_STATUS_NO_MEMORY;
1935 req = rpc_pipe_bind_send(frame, ev, cli, auth);
1937 status = NT_STATUS_NO_MEMORY;
1941 if (!tevent_req_poll(req, ev)) {
1942 status = map_nt_error_from_unix(errno);
1946 status = rpc_pipe_bind_recv(req);
1952 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
1954 unsigned int rpccli_set_timeout(struct rpc_pipe_client *rpc_cli,
1955 unsigned int timeout)
1959 if (rpc_cli->transport == NULL) {
1960 return RPCCLI_DEFAULT_TIMEOUT;
1963 if (rpc_cli->transport->set_timeout == NULL) {
1964 return RPCCLI_DEFAULT_TIMEOUT;
1967 old = rpc_cli->transport->set_timeout(rpc_cli->transport->priv, timeout);
1969 return RPCCLI_DEFAULT_TIMEOUT;
1975 bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli)
1977 if (rpc_cli == NULL) {
1981 if (rpc_cli->transport == NULL) {
1985 return rpc_cli->transport->is_connected(rpc_cli->transport->priv);
1988 struct rpccli_bh_state {
1989 struct rpc_pipe_client *rpc_cli;
1992 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle *h)
1994 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
1995 struct rpccli_bh_state);
1997 return rpccli_is_connected(hs->rpc_cli);
2000 struct rpccli_bh_raw_call_state {
2006 static void rpccli_bh_raw_call_done(struct tevent_req *subreq);
2008 static struct tevent_req *rpccli_bh_raw_call_send(TALLOC_CTX *mem_ctx,
2009 struct tevent_context *ev,
2010 struct dcerpc_binding_handle *h,
2011 const struct GUID *object,
2014 const uint8_t *in_data,
2017 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2018 struct rpccli_bh_state);
2019 struct tevent_req *req;
2020 struct rpccli_bh_raw_call_state *state;
2022 struct tevent_req *subreq;
2024 req = tevent_req_create(mem_ctx, &state,
2025 struct rpccli_bh_raw_call_state);
2029 state->in_data.data = discard_const_p(uint8_t, in_data);
2030 state->in_data.length = in_length;
2032 ok = rpccli_bh_is_connected(h);
2034 tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
2035 return tevent_req_post(req, ev);
2038 subreq = rpc_api_pipe_req_send(state, ev, hs->rpc_cli,
2039 opnum, &state->in_data);
2040 if (tevent_req_nomem(subreq, req)) {
2041 return tevent_req_post(req, ev);
2043 tevent_req_set_callback(subreq, rpccli_bh_raw_call_done, req);
2048 static void rpccli_bh_raw_call_done(struct tevent_req *subreq)
2050 struct tevent_req *req =
2051 tevent_req_callback_data(subreq,
2053 struct rpccli_bh_raw_call_state *state =
2054 tevent_req_data(req,
2055 struct rpccli_bh_raw_call_state);
2058 state->out_flags = 0;
2060 /* TODO: support bigendian responses */
2062 status = rpc_api_pipe_req_recv(subreq, state, &state->out_data);
2063 TALLOC_FREE(subreq);
2064 if (!NT_STATUS_IS_OK(status)) {
2065 tevent_req_nterror(req, status);
2069 tevent_req_done(req);
2072 static NTSTATUS rpccli_bh_raw_call_recv(struct tevent_req *req,
2073 TALLOC_CTX *mem_ctx,
2076 uint32_t *out_flags)
2078 struct rpccli_bh_raw_call_state *state =
2079 tevent_req_data(req,
2080 struct rpccli_bh_raw_call_state);
2083 if (tevent_req_is_nterror(req, &status)) {
2084 tevent_req_received(req);
2088 *out_data = talloc_move(mem_ctx, &state->out_data.data);
2089 *out_length = state->out_data.length;
2090 *out_flags = state->out_flags;
2091 tevent_req_received(req);
2092 return NT_STATUS_OK;
2095 struct rpccli_bh_disconnect_state {
2099 static struct tevent_req *rpccli_bh_disconnect_send(TALLOC_CTX *mem_ctx,
2100 struct tevent_context *ev,
2101 struct dcerpc_binding_handle *h)
2103 struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
2104 struct rpccli_bh_state);
2105 struct tevent_req *req;
2106 struct rpccli_bh_disconnect_state *state;
2109 req = tevent_req_create(mem_ctx, &state,
2110 struct rpccli_bh_disconnect_state);
2115 ok = rpccli_bh_is_connected(h);
2117 tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
2118 return tevent_req_post(req, ev);
2122 * TODO: do a real async disconnect ...
2124 * For now the caller needs to free rpc_cli
2128 tevent_req_done(req);
2129 return tevent_req_post(req, ev);
2132 static NTSTATUS rpccli_bh_disconnect_recv(struct tevent_req *req)
2136 if (tevent_req_is_nterror(req, &status)) {
2137 tevent_req_received(req);
2141 tevent_req_received(req);
2142 return NT_STATUS_OK;
2145 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle *h)
2150 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle *h,
2152 const void *_struct_ptr,
2153 const struct ndr_interface_call *call)
2155 void *struct_ptr = discard_const(_struct_ptr);
2157 if (DEBUGLEVEL < 10) {
2161 if (ndr_flags & NDR_IN) {
2162 ndr_print_function_debug(call->ndr_print,
2167 if (ndr_flags & NDR_OUT) {
2168 ndr_print_function_debug(call->ndr_print,
2175 static const struct dcerpc_binding_handle_ops rpccli_bh_ops = {
2177 .is_connected = rpccli_bh_is_connected,
2178 .raw_call_send = rpccli_bh_raw_call_send,
2179 .raw_call_recv = rpccli_bh_raw_call_recv,
2180 .disconnect_send = rpccli_bh_disconnect_send,
2181 .disconnect_recv = rpccli_bh_disconnect_recv,
2183 .ref_alloc = rpccli_bh_ref_alloc,
2184 .do_ndr_print = rpccli_bh_do_ndr_print,
2187 /* initialise a rpc_pipe_client binding handle */
2188 static struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c)
2190 struct dcerpc_binding_handle *h;
2191 struct rpccli_bh_state *hs;
2193 h = dcerpc_binding_handle_create(c,
2198 struct rpccli_bh_state,
2208 bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16])
2210 struct auth_ntlmssp_state *a = NULL;
2211 struct cli_state *cli;
2213 if (rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_NTLMSSP) {
2214 a = rpc_cli->auth->a_u.auth_ntlmssp_state;
2215 } else if (rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_SPNEGO) {
2216 enum dcerpc_AuthType auth_type;
2220 status = spnego_get_negotiated_mech(
2221 rpc_cli->auth->a_u.spnego_state,
2222 &auth_type, &auth_ctx);
2223 if (!NT_STATUS_IS_OK(status)) {
2227 if (auth_type == DCERPC_AUTH_TYPE_NTLMSSP) {
2228 a = talloc_get_type(auth_ctx,
2229 struct auth_ntlmssp_state);
2234 memcpy(nt_hash, auth_ntlmssp_get_nt_hash(a), 16);
2238 cli = rpc_pipe_np_smb_conn(rpc_cli);
2242 E_md4hash(cli->password ? cli->password : "", nt_hash);
2246 NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx,
2247 struct pipe_auth_data **presult)
2249 struct pipe_auth_data *result;
2251 result = talloc(mem_ctx, struct pipe_auth_data);
2252 if (result == NULL) {
2253 return NT_STATUS_NO_MEMORY;
2256 result->auth_type = DCERPC_AUTH_TYPE_NONE;
2257 result->spnego_type = PIPE_AUTH_TYPE_SPNEGO_NONE;
2258 result->auth_level = DCERPC_AUTH_LEVEL_NONE;
2260 result->user_name = talloc_strdup(result, "");
2261 result->domain = talloc_strdup(result, "");
2262 if ((result->user_name == NULL) || (result->domain == NULL)) {
2263 TALLOC_FREE(result);
2264 return NT_STATUS_NO_MEMORY;
2268 return NT_STATUS_OK;
2271 static int cli_auth_ntlmssp_data_destructor(struct pipe_auth_data *auth)
2273 TALLOC_FREE(auth->a_u.auth_ntlmssp_state);
2277 static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
2278 enum dcerpc_AuthType auth_type,
2279 enum dcerpc_AuthLevel auth_level,
2281 const char *username,
2282 const char *password,
2283 struct pipe_auth_data **presult)
2285 struct pipe_auth_data *result;
2288 result = talloc(mem_ctx, struct pipe_auth_data);
2289 if (result == NULL) {
2290 return NT_STATUS_NO_MEMORY;
2293 result->auth_type = auth_type;
2294 result->auth_level = auth_level;
2296 result->user_name = talloc_strdup(result, username);
2297 result->domain = talloc_strdup(result, domain);
2298 if ((result->user_name == NULL) || (result->domain == NULL)) {
2299 status = NT_STATUS_NO_MEMORY;
2303 status = auth_ntlmssp_client_start(NULL,
2306 lp_client_ntlmv2_auth(),
2307 &result->a_u.auth_ntlmssp_state);
2308 if (!NT_STATUS_IS_OK(status)) {
2312 talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor);
2314 status = auth_ntlmssp_set_username(result->a_u.auth_ntlmssp_state,
2316 if (!NT_STATUS_IS_OK(status)) {
2320 status = auth_ntlmssp_set_domain(result->a_u.auth_ntlmssp_state,
2322 if (!NT_STATUS_IS_OK(status)) {
2326 status = auth_ntlmssp_set_password(result->a_u.auth_ntlmssp_state,
2328 if (!NT_STATUS_IS_OK(status)) {
2333 * Turn off sign+seal to allow selected auth level to turn it back on.
2335 auth_ntlmssp_and_flags(result->a_u.auth_ntlmssp_state,
2336 ~(NTLMSSP_NEGOTIATE_SIGN |
2337 NTLMSSP_NEGOTIATE_SEAL));
2339 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
2340 auth_ntlmssp_or_flags(result->a_u.auth_ntlmssp_state,
2341 NTLMSSP_NEGOTIATE_SIGN);
2342 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
2343 auth_ntlmssp_or_flags(result->a_u.auth_ntlmssp_state,
2344 NTLMSSP_NEGOTIATE_SEAL |
2345 NTLMSSP_NEGOTIATE_SIGN);
2349 return NT_STATUS_OK;
2352 TALLOC_FREE(result);
2356 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
2357 enum dcerpc_AuthLevel auth_level,
2358 struct netlogon_creds_CredentialState *creds,
2359 struct pipe_auth_data **presult)
2361 struct pipe_auth_data *result;
2363 result = talloc(mem_ctx, struct pipe_auth_data);
2364 if (result == NULL) {
2365 return NT_STATUS_NO_MEMORY;
2368 result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
2369 result->spnego_type = PIPE_AUTH_TYPE_SPNEGO_NONE;
2370 result->auth_level = auth_level;
2372 result->user_name = talloc_strdup(result, "");
2373 result->domain = talloc_strdup(result, domain);
2374 if ((result->user_name == NULL) || (result->domain == NULL)) {
2378 result->a_u.schannel_auth = talloc(result, struct schannel_state);
2379 if (result->a_u.schannel_auth == NULL) {
2383 result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
2384 result->a_u.schannel_auth->seq_num = 0;
2385 result->a_u.schannel_auth->initiator = true;
2386 result->a_u.schannel_auth->creds = creds;
2389 return NT_STATUS_OK;
2392 TALLOC_FREE(result);
2393 return NT_STATUS_NO_MEMORY;
2397 * Create an rpc pipe client struct, connecting to a tcp port.
2399 static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
2401 const struct ndr_syntax_id *abstract_syntax,
2402 struct rpc_pipe_client **presult)
2404 struct rpc_pipe_client *result;
2405 struct sockaddr_storage addr;
2409 result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
2410 if (result == NULL) {
2411 return NT_STATUS_NO_MEMORY;
2414 result->abstract_syntax = *abstract_syntax;
2415 result->transfer_syntax = ndr_transfer_syntax;
2417 result->desthost = talloc_strdup(result, host);
2418 result->srv_name_slash = talloc_asprintf_strupper_m(
2419 result, "\\\\%s", result->desthost);
2420 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2421 status = NT_STATUS_NO_MEMORY;
2425 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2426 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2428 if (!resolve_name(host, &addr, 0, false)) {
2429 status = NT_STATUS_NOT_FOUND;
2433 status = open_socket_out(&addr, port, 60, &fd);
2434 if (!NT_STATUS_IS_OK(status)) {
2437 set_socket_options(fd, lp_socket_options());
2439 status = rpc_transport_sock_init(result, fd, &result->transport);
2440 if (!NT_STATUS_IS_OK(status)) {
2445 result->transport->transport = NCACN_IP_TCP;
2447 result->binding_handle = rpccli_bh_create(result);
2448 if (result->binding_handle == NULL) {
2449 TALLOC_FREE(result);
2450 return NT_STATUS_NO_MEMORY;
2454 return NT_STATUS_OK;
2457 TALLOC_FREE(result);
2462 * Determine the tcp port on which a dcerpc interface is listening
2463 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2466 static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
2467 const struct ndr_syntax_id *abstract_syntax,
2471 struct rpc_pipe_client *epm_pipe = NULL;
2472 struct pipe_auth_data *auth = NULL;
2473 struct dcerpc_binding *map_binding = NULL;
2474 struct dcerpc_binding *res_binding = NULL;
2475 struct epm_twr_t *map_tower = NULL;
2476 struct epm_twr_t *res_towers = NULL;
2477 struct policy_handle *entry_handle = NULL;
2478 uint32_t num_towers = 0;
2479 uint32_t max_towers = 1;
2480 struct epm_twr_p_t towers;
2481 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2483 if (pport == NULL) {
2484 status = NT_STATUS_INVALID_PARAMETER;
2488 /* open the connection to the endpoint mapper */
2489 status = rpc_pipe_open_tcp_port(tmp_ctx, host, 135,
2490 &ndr_table_epmapper.syntax_id,
2493 if (!NT_STATUS_IS_OK(status)) {
2497 status = rpccli_anon_bind_data(tmp_ctx, &auth);
2498 if (!NT_STATUS_IS_OK(status)) {
2502 status = rpc_pipe_bind(epm_pipe, auth);
2503 if (!NT_STATUS_IS_OK(status)) {
2507 /* create tower for asking the epmapper */
2509 map_binding = TALLOC_ZERO_P(tmp_ctx, struct dcerpc_binding);
2510 if (map_binding == NULL) {
2511 status = NT_STATUS_NO_MEMORY;
2515 map_binding->transport = NCACN_IP_TCP;
2516 map_binding->object = *abstract_syntax;
2517 map_binding->host = host; /* needed? */
2518 map_binding->endpoint = "0"; /* correct? needed? */
2520 map_tower = TALLOC_ZERO_P(tmp_ctx, struct epm_twr_t);
2521 if (map_tower == NULL) {
2522 status = NT_STATUS_NO_MEMORY;
2526 status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
2527 &(map_tower->tower));
2528 if (!NT_STATUS_IS_OK(status)) {
2532 /* allocate further parameters for the epm_Map call */
2534 res_towers = TALLOC_ARRAY(tmp_ctx, struct epm_twr_t, max_towers);
2535 if (res_towers == NULL) {
2536 status = NT_STATUS_NO_MEMORY;
2539 towers.twr = res_towers;
2541 entry_handle = TALLOC_ZERO_P(tmp_ctx, struct policy_handle);
2542 if (entry_handle == NULL) {
2543 status = NT_STATUS_NO_MEMORY;
2547 /* ask the endpoint mapper for the port */
2549 status = rpccli_epm_Map(epm_pipe,
2551 CONST_DISCARD(struct GUID *,
2552 &(abstract_syntax->uuid)),
2559 if (!NT_STATUS_IS_OK(status)) {
2563 if (num_towers != 1) {
2564 status = NT_STATUS_UNSUCCESSFUL;
2568 /* extract the port from the answer */
2570 status = dcerpc_binding_from_tower(tmp_ctx,
2571 &(towers.twr->tower),
2573 if (!NT_STATUS_IS_OK(status)) {
2577 /* are further checks here necessary? */
2578 if (res_binding->transport != NCACN_IP_TCP) {
2579 status = NT_STATUS_UNSUCCESSFUL;
2583 *pport = (uint16_t)atoi(res_binding->endpoint);
2586 TALLOC_FREE(tmp_ctx);
2591 * Create a rpc pipe client struct, connecting to a host via tcp.
2592 * The port is determined by asking the endpoint mapper on the given
2595 NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
2596 const struct ndr_syntax_id *abstract_syntax,
2597 struct rpc_pipe_client **presult)
2602 status = rpc_pipe_get_tcp_port(host, abstract_syntax, &port);
2603 if (!NT_STATUS_IS_OK(status)) {
2607 return rpc_pipe_open_tcp_port(mem_ctx, host, port,
2608 abstract_syntax, presult);
2611 /********************************************************************
2612 Create a rpc pipe client struct, connecting to a unix domain socket
2613 ********************************************************************/
2614 NTSTATUS rpc_pipe_open_ncalrpc(TALLOC_CTX *mem_ctx, const char *socket_path,
2615 const struct ndr_syntax_id *abstract_syntax,
2616 struct rpc_pipe_client **presult)
2618 struct rpc_pipe_client *result;
2619 struct sockaddr_un addr;
2623 result = talloc_zero(mem_ctx, struct rpc_pipe_client);
2624 if (result == NULL) {
2625 return NT_STATUS_NO_MEMORY;
2628 result->abstract_syntax = *abstract_syntax;
2629 result->transfer_syntax = ndr_transfer_syntax;
2631 result->desthost = get_myname(result);
2632 result->srv_name_slash = talloc_asprintf_strupper_m(
2633 result, "\\\\%s", result->desthost);
2634 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2635 status = NT_STATUS_NO_MEMORY;
2639 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2640 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2642 fd = socket(AF_UNIX, SOCK_STREAM, 0);
2644 status = map_nt_error_from_unix(errno);
2649 addr.sun_family = AF_UNIX;
2650 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
2652 if (sys_connect(fd, (struct sockaddr *)(void *)&addr) == -1) {
2653 DEBUG(0, ("connect(%s) failed: %s\n", socket_path,
2656 return map_nt_error_from_unix(errno);
2659 status = rpc_transport_sock_init(result, fd, &result->transport);
2660 if (!NT_STATUS_IS_OK(status)) {
2665 result->transport->transport = NCALRPC;
2667 result->binding_handle = rpccli_bh_create(result);
2668 if (result->binding_handle == NULL) {
2669 TALLOC_FREE(result);
2670 return NT_STATUS_NO_MEMORY;
2674 return NT_STATUS_OK;
2677 TALLOC_FREE(result);
2681 struct rpc_pipe_client_np_ref {
2682 struct cli_state *cli;
2683 struct rpc_pipe_client *pipe;
2686 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref *np_ref)
2688 DLIST_REMOVE(np_ref->cli->pipe_list, np_ref->pipe);
2692 /****************************************************************************
2693 Open a named pipe over SMB to a remote server.
2695 * CAVEAT CALLER OF THIS FUNCTION:
2696 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2697 * so be sure that this function is called AFTER any structure (vs pointer)
2698 * assignment of the cli. In particular, libsmbclient does structure
2699 * assignments of cli, which invalidates the data in the returned
2700 * rpc_pipe_client if this function is called before the structure assignment
2703 ****************************************************************************/
2705 static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
2706 const struct ndr_syntax_id *abstract_syntax,
2707 struct rpc_pipe_client **presult)
2709 struct rpc_pipe_client *result;
2711 struct rpc_pipe_client_np_ref *np_ref;
2713 /* sanity check to protect against crashes */
2716 return NT_STATUS_INVALID_HANDLE;
2719 result = TALLOC_ZERO_P(NULL, struct rpc_pipe_client);
2720 if (result == NULL) {
2721 return NT_STATUS_NO_MEMORY;
2724 result->abstract_syntax = *abstract_syntax;
2725 result->transfer_syntax = ndr_transfer_syntax;
2726 result->desthost = talloc_strdup(result, cli->desthost);
2727 result->srv_name_slash = talloc_asprintf_strupper_m(
2728 result, "\\\\%s", result->desthost);
2730 result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
2731 result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
2733 if ((result->desthost == NULL) || (result->srv_name_slash == NULL)) {
2734 TALLOC_FREE(result);
2735 return NT_STATUS_NO_MEMORY;
2738 status = rpc_transport_np_init(result, cli, abstract_syntax,
2739 &result->transport);
2740 if (!NT_STATUS_IS_OK(status)) {
2741 TALLOC_FREE(result);
2745 result->transport->transport = NCACN_NP;
2747 np_ref = talloc(result->transport, struct rpc_pipe_client_np_ref);
2748 if (np_ref == NULL) {
2749 TALLOC_FREE(result);
2750 return NT_STATUS_NO_MEMORY;
2753 np_ref->pipe = result;
2755 DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
2756 talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
2758 result->binding_handle = rpccli_bh_create(result);
2759 if (result->binding_handle == NULL) {
2760 TALLOC_FREE(result);
2761 return NT_STATUS_NO_MEMORY;
2765 return NT_STATUS_OK;
2768 /****************************************************************************
2769 Open a pipe to a remote server.
2770 ****************************************************************************/
2772 static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
2773 enum dcerpc_transport_t transport,
2774 const struct ndr_syntax_id *interface,
2775 struct rpc_pipe_client **presult)
2777 switch (transport) {
2779 return rpc_pipe_open_tcp(NULL, cli->desthost, interface,
2782 return rpc_pipe_open_np(cli, interface, presult);
2784 return NT_STATUS_NOT_IMPLEMENTED;
2788 /****************************************************************************
2789 Open a named pipe to an SMB server and bind anonymously.
2790 ****************************************************************************/
2792 NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
2793 enum dcerpc_transport_t transport,
2794 const struct ndr_syntax_id *interface,
2795 struct rpc_pipe_client **presult)
2797 struct rpc_pipe_client *result;
2798 struct pipe_auth_data *auth;
2801 status = cli_rpc_pipe_open(cli, transport, interface, &result);
2802 if (!NT_STATUS_IS_OK(status)) {
2806 status = rpccli_anon_bind_data(result, &auth);
2807 if (!NT_STATUS_IS_OK(status)) {
2808 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
2809 nt_errstr(status)));
2810 TALLOC_FREE(result);
2815 * This is a bit of an abstraction violation due to the fact that an
2816 * anonymous bind on an authenticated SMB inherits the user/domain
2817 * from the enclosing SMB creds
2820 TALLOC_FREE(auth->user_name);
2821 TALLOC_FREE(auth->domain);
2823 auth->user_name = talloc_strdup(auth, cli->user_name);
2824 auth->domain = talloc_strdup(auth, cli->domain);
2825 auth->user_session_key = data_blob_talloc(auth,
2826 cli->user_session_key.data,
2827 cli->user_session_key.length);
2829 if ((auth->user_name == NULL) || (auth->domain == NULL)) {
2830 TALLOC_FREE(result);
2831 return NT_STATUS_NO_MEMORY;
2834 status = rpc_pipe_bind(result, auth);
2835 if (!NT_STATUS_IS_OK(status)) {
2837 if (ndr_syntax_id_equal(interface,
2838 &ndr_table_dssetup.syntax_id)) {
2839 /* non AD domains just don't have this pipe, avoid
2840 * level 0 statement in that case - gd */
2843 DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
2844 "%s failed with error %s\n",
2845 get_pipe_name_from_syntax(talloc_tos(), interface),
2846 nt_errstr(status) ));
2847 TALLOC_FREE(result);
2851 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
2852 "%s and bound anonymously.\n",
2853 get_pipe_name_from_syntax(talloc_tos(), interface),
2857 return NT_STATUS_OK;
2860 /****************************************************************************
2861 ****************************************************************************/
2863 NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
2864 const struct ndr_syntax_id *interface,
2865 struct rpc_pipe_client **presult)
2867 return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
2868 interface, presult);
2871 /****************************************************************************
2872 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
2873 ****************************************************************************/
2875 NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
2876 const struct ndr_syntax_id *interface,
2877 enum dcerpc_transport_t transport,
2878 enum dcerpc_AuthLevel auth_level,
2880 const char *username,
2881 const char *password,
2882 struct rpc_pipe_client **presult)
2884 struct rpc_pipe_client *result;
2885 struct pipe_auth_data *auth = NULL;
2886 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
2889 status = cli_rpc_pipe_open(cli, transport, interface, &result);
2890 if (!NT_STATUS_IS_OK(status)) {
2894 status = rpccli_ntlmssp_bind_data(result,
2895 auth_type, auth_level,
2896 domain, username, password,
2898 if (!NT_STATUS_IS_OK(status)) {
2899 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
2900 nt_errstr(status)));
2904 status = rpc_pipe_bind(result, auth);
2905 if (!NT_STATUS_IS_OK(status)) {
2906 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
2907 nt_errstr(status) ));
2911 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
2912 "machine %s and bound NTLMSSP as user %s\\%s.\n",
2913 get_pipe_name_from_syntax(talloc_tos(), interface),
2914 cli->desthost, domain, username ));
2917 return NT_STATUS_OK;
2921 TALLOC_FREE(result);
2925 /****************************************************************************
2926 Get a the schannel session key out of an already opened netlogon pipe.
2927 ****************************************************************************/
2928 static NTSTATUS get_schannel_session_key_common(struct rpc_pipe_client *netlogon_pipe,
2929 struct cli_state *cli,
2933 enum netr_SchannelType sec_chan_type = 0;
2934 unsigned char machine_pwd[16];
2935 const char *machine_account;
2938 /* Get the machine account credentials from secrets.tdb. */
2939 if (!get_trust_pw_hash(domain, machine_pwd, &machine_account,
2942 DEBUG(0, ("get_schannel_session_key: could not fetch "
2943 "trust account password for domain '%s'\n",
2945 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2948 status = rpccli_netlogon_setup_creds(netlogon_pipe,
2949 cli->desthost, /* server name */
2950 domain, /* domain */
2951 global_myname(), /* client name */
2952 machine_account, /* machine account name */
2957 if (!NT_STATUS_IS_OK(status)) {
2958 DEBUG(3, ("get_schannel_session_key_common: "
2959 "rpccli_netlogon_setup_creds failed with result %s "
2960 "to server %s, domain %s, machine account %s.\n",
2961 nt_errstr(status), cli->desthost, domain,
2966 if (((*pneg_flags) & NETLOGON_NEG_SCHANNEL) == 0) {
2967 DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
2969 return NT_STATUS_INVALID_NETWORK_RESPONSE;
2972 return NT_STATUS_OK;;
2975 /****************************************************************************
2976 Open a netlogon pipe and get the schannel session key.
2977 Now exposed to external callers.
2978 ****************************************************************************/
2981 NTSTATUS get_schannel_session_key(struct cli_state *cli,
2984 struct rpc_pipe_client **presult)
2986 struct rpc_pipe_client *netlogon_pipe = NULL;
2989 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
2991 if (!NT_STATUS_IS_OK(status)) {
2995 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
2997 if (!NT_STATUS_IS_OK(status)) {
2998 TALLOC_FREE(netlogon_pipe);
3002 *presult = netlogon_pipe;
3003 return NT_STATUS_OK;
3006 /****************************************************************************
3008 Open a named pipe to an SMB server and bind using schannel (bind type 68)
3009 using session_key. sign and seal.
3011 The *pdc will be stolen onto this new pipe
3012 ****************************************************************************/
3014 NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
3015 const struct ndr_syntax_id *interface,
3016 enum dcerpc_transport_t transport,
3017 enum dcerpc_AuthLevel auth_level,
3019 struct netlogon_creds_CredentialState **pdc,
3020 struct rpc_pipe_client **presult)
3022 struct rpc_pipe_client *result;
3023 struct pipe_auth_data *auth;
3026 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3027 if (!NT_STATUS_IS_OK(status)) {
3031 status = rpccli_schannel_bind_data(result, domain, auth_level,
3033 if (!NT_STATUS_IS_OK(status)) {
3034 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
3035 nt_errstr(status)));
3036 TALLOC_FREE(result);
3040 status = rpc_pipe_bind(result, auth);
3041 if (!NT_STATUS_IS_OK(status)) {
3042 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
3043 "cli_rpc_pipe_bind failed with error %s\n",
3044 nt_errstr(status) ));
3045 TALLOC_FREE(result);
3050 * The credentials on a new netlogon pipe are the ones we are passed
3051 * in - reference them in
3053 result->dc = talloc_move(result, pdc);
3055 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
3056 "for domain %s and bound using schannel.\n",
3057 get_pipe_name_from_syntax(talloc_tos(), interface),
3058 cli->desthost, domain ));
3061 return NT_STATUS_OK;
3064 /****************************************************************************
3065 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3066 Fetch the session key ourselves using a temporary netlogon pipe. This
3067 version uses an ntlmssp auth bound netlogon pipe to get the key.
3068 ****************************************************************************/
3070 static NTSTATUS get_schannel_session_key_auth_ntlmssp(struct cli_state *cli,
3072 const char *username,
3073 const char *password,
3075 struct rpc_pipe_client **presult)
3077 struct rpc_pipe_client *netlogon_pipe = NULL;
3080 status = cli_rpc_pipe_open_spnego_ntlmssp(
3081 cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
3082 DCERPC_AUTH_LEVEL_PRIVACY,
3083 domain, username, password, &netlogon_pipe);
3084 if (!NT_STATUS_IS_OK(status)) {
3088 status = get_schannel_session_key_common(netlogon_pipe, cli, domain,
3090 if (!NT_STATUS_IS_OK(status)) {
3091 TALLOC_FREE(netlogon_pipe);
3095 *presult = netlogon_pipe;
3096 return NT_STATUS_OK;
3099 /****************************************************************************
3100 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3101 Fetch the session key ourselves using a temporary netlogon pipe. This version
3102 uses an ntlmssp bind to get the session key.
3103 ****************************************************************************/
3105 NTSTATUS cli_rpc_pipe_open_ntlmssp_auth_schannel(struct cli_state *cli,
3106 const struct ndr_syntax_id *interface,
3107 enum dcerpc_transport_t transport,
3108 enum dcerpc_AuthLevel auth_level,
3110 const char *username,
3111 const char *password,
3112 struct rpc_pipe_client **presult)
3114 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3115 struct rpc_pipe_client *netlogon_pipe = NULL;
3116 struct rpc_pipe_client *result = NULL;
3119 status = get_schannel_session_key_auth_ntlmssp(
3120 cli, domain, username, password, &neg_flags, &netlogon_pipe);
3121 if (!NT_STATUS_IS_OK(status)) {
3122 DEBUG(0,("cli_rpc_pipe_open_ntlmssp_auth_schannel: failed to get schannel session "
3123 "key from server %s for domain %s.\n",
3124 cli->desthost, domain ));
3128 status = cli_rpc_pipe_open_schannel_with_key(
3129 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3132 /* Now we've bound using the session key we can close the netlog pipe. */
3133 TALLOC_FREE(netlogon_pipe);
3135 if (NT_STATUS_IS_OK(status)) {
3141 /****************************************************************************
3142 Open a named pipe to an SMB server and bind using schannel (bind type 68).
3143 Fetch the session key ourselves using a temporary netlogon pipe.
3144 ****************************************************************************/
3146 NTSTATUS cli_rpc_pipe_open_schannel(struct cli_state *cli,
3147 const struct ndr_syntax_id *interface,
3148 enum dcerpc_transport_t transport,
3149 enum dcerpc_AuthLevel auth_level,
3151 struct rpc_pipe_client **presult)
3153 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
3154 struct rpc_pipe_client *netlogon_pipe = NULL;
3155 struct rpc_pipe_client *result = NULL;
3158 status = get_schannel_session_key(cli, domain, &neg_flags,
3160 if (!NT_STATUS_IS_OK(status)) {
3161 DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
3162 "key from server %s for domain %s.\n",
3163 cli->desthost, domain ));
3167 status = cli_rpc_pipe_open_schannel_with_key(
3168 cli, interface, transport, auth_level, domain, &netlogon_pipe->dc,
3171 /* Now we've bound using the session key we can close the netlog pipe. */
3172 TALLOC_FREE(netlogon_pipe);
3174 if (NT_STATUS_IS_OK(status)) {
3181 /****************************************************************************
3182 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
3183 The idea is this can be called with service_princ, username and password all
3184 NULL so long as the caller has a TGT.
3185 ****************************************************************************/
3187 NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli,
3188 const struct ndr_syntax_id *interface,
3189 enum dcerpc_transport_t transport,
3190 enum dcerpc_AuthLevel auth_level,
3192 const char *username,
3193 const char *password,
3194 struct rpc_pipe_client **presult)
3196 struct rpc_pipe_client *result;
3197 struct pipe_auth_data *auth;
3200 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3201 if (!NT_STATUS_IS_OK(status)) {
3205 auth = talloc(result, struct pipe_auth_data);
3207 status = NT_STATUS_NO_MEMORY;
3210 auth->auth_type = DCERPC_AUTH_TYPE_KRB5;
3211 auth->auth_level = auth_level;
3216 auth->user_name = talloc_strdup(auth, username);
3217 if (!auth->user_name) {
3218 status = NT_STATUS_NO_MEMORY;
3222 /* Fixme, should we fetch/set the Realm ? */
3223 auth->domain = talloc_strdup(auth, "");
3224 if (!auth->domain) {
3225 status = NT_STATUS_NO_MEMORY;
3229 status = gse_init_client(auth, auth->auth_type, auth->auth_level,
3230 NULL, server, "cifs", username, password,
3231 GSS_C_DCE_STYLE, &auth->a_u.gssapi_state);
3233 if (!NT_STATUS_IS_OK(status)) {
3234 DEBUG(0, ("gse_init_client returned %s\n",
3235 nt_errstr(status)));
3239 status = rpc_pipe_bind(result, auth);
3240 if (!NT_STATUS_IS_OK(status)) {
3241 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3242 nt_errstr(status)));
3247 return NT_STATUS_OK;
3250 TALLOC_FREE(result);
3254 NTSTATUS cli_rpc_pipe_open_spnego_krb5(struct cli_state *cli,
3255 const struct ndr_syntax_id *interface,
3256 enum dcerpc_transport_t transport,
3257 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;
3267 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3268 if (!NT_STATUS_IS_OK(status)) {
3272 auth = talloc(result, struct pipe_auth_data);
3274 status = NT_STATUS_NO_MEMORY;
3277 auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
3278 auth->auth_level = auth_level;
3280 auth->spnego_type = PIPE_AUTH_TYPE_SPNEGO_KRB5;
3285 auth->user_name = talloc_strdup(auth, username);
3286 if (!auth->user_name) {
3287 status = NT_STATUS_NO_MEMORY;
3291 /* Fixme, should we fetch/set the Realm ? */
3292 auth->domain = talloc_strdup(auth, "");
3293 if (!auth->domain) {
3294 status = NT_STATUS_NO_MEMORY;
3298 status = spnego_gssapi_init_client(auth, auth->auth_level,
3299 NULL, server, "cifs",
3302 &auth->a_u.spnego_state);
3303 if (!NT_STATUS_IS_OK(status)) {
3304 DEBUG(0, ("spnego_init_client returned %s\n",
3305 nt_errstr(status)));
3309 status = rpc_pipe_bind(result, auth);
3310 if (!NT_STATUS_IS_OK(status)) {
3311 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3312 nt_errstr(status)));
3317 return NT_STATUS_OK;
3320 TALLOC_FREE(result);
3324 NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
3325 const struct ndr_syntax_id *interface,
3326 enum dcerpc_transport_t transport,
3327 enum dcerpc_AuthLevel auth_level,
3329 const char *username,
3330 const char *password,
3331 struct rpc_pipe_client **presult)
3333 struct rpc_pipe_client *result;
3334 struct pipe_auth_data *auth;
3337 status = cli_rpc_pipe_open(cli, transport, interface, &result);
3338 if (!NT_STATUS_IS_OK(status)) {
3342 auth = talloc(result, struct pipe_auth_data);
3344 status = NT_STATUS_NO_MEMORY;
3347 auth->auth_type = DCERPC_AUTH_TYPE_SPNEGO;
3348 auth->auth_level = auth_level;
3353 auth->user_name = talloc_strdup(auth, username);
3354 if (!auth->user_name) {
3355 status = NT_STATUS_NO_MEMORY;
3362 auth->domain = talloc_strdup(auth, domain);
3363 if (!auth->domain) {
3364 status = NT_STATUS_NO_MEMORY;
3368 status = spnego_ntlmssp_init_client(auth, auth->auth_level,
3369 domain, username, password,
3370 &auth->a_u.spnego_state);
3371 if (!NT_STATUS_IS_OK(status)) {
3372 DEBUG(0, ("spnego_init_client returned %s\n",
3373 nt_errstr(status)));
3377 status = rpc_pipe_bind(result, auth);
3378 if (!NT_STATUS_IS_OK(status)) {
3379 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3380 nt_errstr(status)));
3385 return NT_STATUS_OK;
3388 TALLOC_FREE(result);
3392 NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx,
3393 struct rpc_pipe_client *cli,
3394 DATA_BLOB *session_key)
3396 struct pipe_auth_data *a = cli->auth;
3397 DATA_BLOB sk = data_blob_null;
3398 bool make_dup = false;
3400 if (!session_key || !cli) {
3401 return NT_STATUS_INVALID_PARAMETER;
3405 return NT_STATUS_INVALID_PARAMETER;
3408 switch (cli->auth->auth_type) {
3409 case DCERPC_AUTH_TYPE_SCHANNEL:
3410 sk = data_blob_const(a->a_u.schannel_auth->creds->session_key,
3414 case DCERPC_AUTH_TYPE_SPNEGO:
3415 sk = spnego_get_session_key(mem_ctx, a->a_u.spnego_state);
3418 case DCERPC_AUTH_TYPE_NTLMSSP:
3419 sk = auth_ntlmssp_get_session_key(a->a_u.auth_ntlmssp_state);
3422 case DCERPC_AUTH_TYPE_KRB5:
3423 sk = gse_get_session_key(mem_ctx, a->a_u.gssapi_state);
3426 case DCERPC_AUTH_TYPE_NONE:
3427 sk = data_blob_const(a->user_session_key.data,
3428 a->user_session_key.length);
3436 return NT_STATUS_NO_USER_SESSION_KEY;
3440 *session_key = data_blob_dup_talloc(mem_ctx, &sk);
3445 return NT_STATUS_OK;