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 "../lib/util/tevent_ntstatus.h"
23 #include "librpc/gen_ndr/ndr_epmapper_c.h"
24 #include "../librpc/gen_ndr/ndr_schannel.h"
25 #include "../librpc/gen_ndr/ndr_dssetup.h"
26 #include "../libcli/auth/schannel.h"
27 #include "../libcli/auth/spnego.h"
28 #include "../auth/ntlmssp/ntlmssp.h"
29 #include "ntlmssp_wrap.h"
30 #include "librpc/gen_ndr/ndr_dcerpc.h"
31 #include "librpc/rpc/dcerpc.h"
32 #include "librpc/crypto/gse.h"
33 #include "librpc/crypto/spnego.h"
36 #include "libsmb/libsmb.h"
37 #include "auth/gensec/gensec.h"
40 #define DBGC_CLASS DBGC_RPC_CLI
42 /********************************************************************
43 Pipe description for a DEBUG
44 ********************************************************************/
45 static const char *rpccli_pipe_txt(TALLOC_CTX
*mem_ctx
,
46 struct rpc_pipe_client
*cli
)
48 char *result
= talloc_asprintf(mem_ctx
, "host %s", cli
->desthost
);
55 /********************************************************************
57 ********************************************************************/
59 static uint32
get_rpc_call_id(void)
61 static uint32 call_id
= 0;
65 /*******************************************************************
66 Use SMBreadX to get rest of one fragment's worth of rpc data.
67 Reads the whole size or give an error message
68 ********************************************************************/
70 struct rpc_read_state
{
71 struct event_context
*ev
;
72 struct rpc_cli_transport
*transport
;
78 static void rpc_read_done(struct tevent_req
*subreq
);
80 static struct tevent_req
*rpc_read_send(TALLOC_CTX
*mem_ctx
,
81 struct event_context
*ev
,
82 struct rpc_cli_transport
*transport
,
83 uint8_t *data
, size_t size
)
85 struct tevent_req
*req
, *subreq
;
86 struct rpc_read_state
*state
;
88 req
= tevent_req_create(mem_ctx
, &state
, struct rpc_read_state
);
93 state
->transport
= transport
;
98 DEBUG(5, ("rpc_read_send: data_to_read: %u\n", (unsigned int)size
));
100 subreq
= transport
->read_send(state
, ev
, (uint8_t *)data
, size
,
102 if (subreq
== NULL
) {
105 tevent_req_set_callback(subreq
, rpc_read_done
, req
);
113 static void rpc_read_done(struct tevent_req
*subreq
)
115 struct tevent_req
*req
= tevent_req_callback_data(
116 subreq
, struct tevent_req
);
117 struct rpc_read_state
*state
= tevent_req_data(
118 req
, struct rpc_read_state
);
122 status
= state
->transport
->read_recv(subreq
, &received
);
124 if (!NT_STATUS_IS_OK(status
)) {
125 tevent_req_nterror(req
, status
);
129 state
->num_read
+= received
;
130 if (state
->num_read
== state
->size
) {
131 tevent_req_done(req
);
135 subreq
= state
->transport
->read_send(state
, state
->ev
,
136 state
->data
+ state
->num_read
,
137 state
->size
- state
->num_read
,
138 state
->transport
->priv
);
139 if (tevent_req_nomem(subreq
, req
)) {
142 tevent_req_set_callback(subreq
, rpc_read_done
, req
);
145 static NTSTATUS
rpc_read_recv(struct tevent_req
*req
)
147 return tevent_req_simple_recv_ntstatus(req
);
150 struct rpc_write_state
{
151 struct event_context
*ev
;
152 struct rpc_cli_transport
*transport
;
158 static void rpc_write_done(struct tevent_req
*subreq
);
160 static struct tevent_req
*rpc_write_send(TALLOC_CTX
*mem_ctx
,
161 struct event_context
*ev
,
162 struct rpc_cli_transport
*transport
,
163 const uint8_t *data
, size_t size
)
165 struct tevent_req
*req
, *subreq
;
166 struct rpc_write_state
*state
;
168 req
= tevent_req_create(mem_ctx
, &state
, struct rpc_write_state
);
173 state
->transport
= transport
;
176 state
->num_written
= 0;
178 DEBUG(5, ("rpc_write_send: data_to_write: %u\n", (unsigned int)size
));
180 subreq
= transport
->write_send(state
, ev
, data
, size
, transport
->priv
);
181 if (subreq
== NULL
) {
184 tevent_req_set_callback(subreq
, rpc_write_done
, req
);
191 static void rpc_write_done(struct tevent_req
*subreq
)
193 struct tevent_req
*req
= tevent_req_callback_data(
194 subreq
, struct tevent_req
);
195 struct rpc_write_state
*state
= tevent_req_data(
196 req
, struct rpc_write_state
);
200 status
= state
->transport
->write_recv(subreq
, &written
);
202 if (!NT_STATUS_IS_OK(status
)) {
203 tevent_req_nterror(req
, status
);
207 state
->num_written
+= written
;
209 if (state
->num_written
== state
->size
) {
210 tevent_req_done(req
);
214 subreq
= state
->transport
->write_send(state
, state
->ev
,
215 state
->data
+ state
->num_written
,
216 state
->size
- state
->num_written
,
217 state
->transport
->priv
);
218 if (tevent_req_nomem(subreq
, req
)) {
221 tevent_req_set_callback(subreq
, rpc_write_done
, req
);
224 static NTSTATUS
rpc_write_recv(struct tevent_req
*req
)
226 return tevent_req_simple_recv_ntstatus(req
);
230 /****************************************************************************
231 Try and get a PDU's worth of data from current_pdu. If not, then read more
233 ****************************************************************************/
235 struct get_complete_frag_state
{
236 struct event_context
*ev
;
237 struct rpc_pipe_client
*cli
;
242 static void get_complete_frag_got_header(struct tevent_req
*subreq
);
243 static void get_complete_frag_got_rest(struct tevent_req
*subreq
);
245 static struct tevent_req
*get_complete_frag_send(TALLOC_CTX
*mem_ctx
,
246 struct event_context
*ev
,
247 struct rpc_pipe_client
*cli
,
250 struct tevent_req
*req
, *subreq
;
251 struct get_complete_frag_state
*state
;
255 req
= tevent_req_create(mem_ctx
, &state
,
256 struct get_complete_frag_state
);
262 state
->frag_len
= RPC_HEADER_LEN
;
265 received
= pdu
->length
;
266 if (received
< RPC_HEADER_LEN
) {
267 if (!data_blob_realloc(mem_ctx
, pdu
, RPC_HEADER_LEN
)) {
268 status
= NT_STATUS_NO_MEMORY
;
271 subreq
= rpc_read_send(state
, state
->ev
,
272 state
->cli
->transport
,
273 pdu
->data
+ received
,
274 RPC_HEADER_LEN
- received
);
275 if (subreq
== NULL
) {
276 status
= NT_STATUS_NO_MEMORY
;
279 tevent_req_set_callback(subreq
, get_complete_frag_got_header
,
284 state
->frag_len
= dcerpc_get_frag_length(pdu
);
287 * Ensure we have frag_len bytes of data.
289 if (received
< state
->frag_len
) {
290 if (!data_blob_realloc(NULL
, pdu
, state
->frag_len
)) {
291 status
= NT_STATUS_NO_MEMORY
;
294 subreq
= rpc_read_send(state
, state
->ev
,
295 state
->cli
->transport
,
296 pdu
->data
+ received
,
297 state
->frag_len
- received
);
298 if (subreq
== NULL
) {
299 status
= NT_STATUS_NO_MEMORY
;
302 tevent_req_set_callback(subreq
, get_complete_frag_got_rest
,
307 status
= NT_STATUS_OK
;
309 if (NT_STATUS_IS_OK(status
)) {
310 tevent_req_done(req
);
312 tevent_req_nterror(req
, status
);
314 return tevent_req_post(req
, ev
);
317 static void get_complete_frag_got_header(struct tevent_req
*subreq
)
319 struct tevent_req
*req
= tevent_req_callback_data(
320 subreq
, struct tevent_req
);
321 struct get_complete_frag_state
*state
= tevent_req_data(
322 req
, struct get_complete_frag_state
);
325 status
= rpc_read_recv(subreq
);
327 if (!NT_STATUS_IS_OK(status
)) {
328 tevent_req_nterror(req
, status
);
332 state
->frag_len
= dcerpc_get_frag_length(state
->pdu
);
334 if (!data_blob_realloc(NULL
, state
->pdu
, state
->frag_len
)) {
335 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
340 * We're here in this piece of code because we've read exactly
341 * RPC_HEADER_LEN bytes into state->pdu.
344 subreq
= rpc_read_send(state
, state
->ev
, state
->cli
->transport
,
345 state
->pdu
->data
+ RPC_HEADER_LEN
,
346 state
->frag_len
- RPC_HEADER_LEN
);
347 if (tevent_req_nomem(subreq
, req
)) {
350 tevent_req_set_callback(subreq
, get_complete_frag_got_rest
, req
);
353 static void get_complete_frag_got_rest(struct tevent_req
*subreq
)
355 struct tevent_req
*req
= tevent_req_callback_data(
356 subreq
, struct tevent_req
);
359 status
= rpc_read_recv(subreq
);
361 if (!NT_STATUS_IS_OK(status
)) {
362 tevent_req_nterror(req
, status
);
365 tevent_req_done(req
);
368 static NTSTATUS
get_complete_frag_recv(struct tevent_req
*req
)
370 return tevent_req_simple_recv_ntstatus(req
);
373 /****************************************************************************
374 Do basic authentication checks on an incoming pdu.
375 ****************************************************************************/
377 static NTSTATUS
cli_pipe_validate_current_pdu(TALLOC_CTX
*mem_ctx
,
378 struct rpc_pipe_client
*cli
,
379 struct ncacn_packet
*pkt
,
381 uint8_t expected_pkt_type
,
383 DATA_BLOB
*reply_pdu
)
385 struct dcerpc_response
*r
;
386 NTSTATUS ret
= NT_STATUS_OK
;
390 * Point the return values at the real data including the RPC
391 * header. Just in case the caller wants it.
395 /* Ensure we have the correct type. */
396 switch (pkt
->ptype
) {
397 case DCERPC_PKT_ALTER_RESP
:
398 case DCERPC_PKT_BIND_ACK
:
400 /* Client code never receives this kind of packets */
404 case DCERPC_PKT_RESPONSE
:
406 r
= &pkt
->u
.response
;
408 /* Here's where we deal with incoming sign/seal. */
409 ret
= dcerpc_check_auth(cli
->auth
, pkt
,
410 &r
->stub_and_verifier
,
411 DCERPC_RESPONSE_LENGTH
,
413 if (!NT_STATUS_IS_OK(ret
)) {
417 if (pkt
->frag_length
< DCERPC_RESPONSE_LENGTH
+ pad_len
) {
418 return NT_STATUS_BUFFER_TOO_SMALL
;
421 /* Point the return values at the NDR data. */
422 rdata
->data
= r
->stub_and_verifier
.data
;
424 if (pkt
->auth_length
) {
425 /* We've already done integer wrap tests in
426 * dcerpc_check_auth(). */
427 rdata
->length
= r
->stub_and_verifier
.length
429 - DCERPC_AUTH_TRAILER_LENGTH
432 rdata
->length
= r
->stub_and_verifier
.length
;
435 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
436 (long unsigned int)pdu
->length
,
437 (long unsigned int)rdata
->length
,
438 (unsigned int)pad_len
));
441 * If this is the first reply, and the allocation hint is
442 * reasonable, try and set up the reply_pdu DATA_BLOB to the
446 if ((reply_pdu
->length
== 0) &&
447 r
->alloc_hint
&& (r
->alloc_hint
< 15*1024*1024)) {
448 if (!data_blob_realloc(mem_ctx
, reply_pdu
,
450 DEBUG(0, ("reply alloc hint %d too "
451 "large to allocate\n",
452 (int)r
->alloc_hint
));
453 return NT_STATUS_NO_MEMORY
;
459 case DCERPC_PKT_BIND_NAK
:
460 DEBUG(1, (__location__
": Bind NACK received from %s!\n",
461 rpccli_pipe_txt(talloc_tos(), cli
)));
462 /* Use this for now... */
463 return NT_STATUS_NETWORK_ACCESS_DENIED
;
465 case DCERPC_PKT_FAULT
:
467 DEBUG(1, (__location__
": RPC fault code %s received "
469 dcerpc_errstr(talloc_tos(),
470 pkt
->u
.fault
.status
),
471 rpccli_pipe_txt(talloc_tos(), cli
)));
473 return dcerpc_fault_to_nt_status(pkt
->u
.fault
.status
);
476 DEBUG(0, (__location__
"Unknown packet type %u received "
478 (unsigned int)pkt
->ptype
,
479 rpccli_pipe_txt(talloc_tos(), cli
)));
480 return NT_STATUS_INVALID_INFO_CLASS
;
483 if (pkt
->ptype
!= expected_pkt_type
) {
484 DEBUG(3, (__location__
": Connection to %s got an unexpected "
485 "RPC packet type - %u, not %u\n",
486 rpccli_pipe_txt(talloc_tos(), cli
),
487 pkt
->ptype
, expected_pkt_type
));
488 return NT_STATUS_INVALID_INFO_CLASS
;
491 /* Do this just before return - we don't want to modify any rpc header
492 data before now as we may have needed to do cryptographic actions on
495 if ((pkt
->ptype
== DCERPC_PKT_BIND_ACK
) &&
496 !(pkt
->pfc_flags
& DCERPC_PFC_FLAG_LAST
)) {
497 DEBUG(5, (__location__
": bug in server (AS/U?), setting "
498 "fragment first/last ON.\n"));
499 pkt
->pfc_flags
|= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
505 /****************************************************************************
506 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
507 ****************************************************************************/
509 struct cli_api_pipe_state
{
510 struct event_context
*ev
;
511 struct rpc_cli_transport
*transport
;
516 static void cli_api_pipe_trans_done(struct tevent_req
*subreq
);
517 static void cli_api_pipe_write_done(struct tevent_req
*subreq
);
518 static void cli_api_pipe_read_done(struct tevent_req
*subreq
);
520 static struct tevent_req
*cli_api_pipe_send(TALLOC_CTX
*mem_ctx
,
521 struct event_context
*ev
,
522 struct rpc_cli_transport
*transport
,
523 uint8_t *data
, size_t data_len
,
524 uint32_t max_rdata_len
)
526 struct tevent_req
*req
, *subreq
;
527 struct cli_api_pipe_state
*state
;
530 req
= tevent_req_create(mem_ctx
, &state
, struct cli_api_pipe_state
);
535 state
->transport
= transport
;
537 if (max_rdata_len
< RPC_HEADER_LEN
) {
539 * For a RPC reply we always need at least RPC_HEADER_LEN
540 * bytes. We check this here because we will receive
541 * RPC_HEADER_LEN bytes in cli_trans_sock_send_done.
543 status
= NT_STATUS_INVALID_PARAMETER
;
547 if (transport
->trans_send
!= NULL
) {
548 subreq
= transport
->trans_send(state
, ev
, data
, data_len
,
549 max_rdata_len
, transport
->priv
);
550 if (subreq
== NULL
) {
553 tevent_req_set_callback(subreq
, cli_api_pipe_trans_done
, req
);
558 * If the transport does not provide a "trans" routine, i.e. for
559 * example the ncacn_ip_tcp transport, do the write/read step here.
562 subreq
= rpc_write_send(state
, ev
, transport
, data
, data_len
);
563 if (subreq
== NULL
) {
566 tevent_req_set_callback(subreq
, cli_api_pipe_write_done
, req
);
570 tevent_req_nterror(req
, status
);
571 return tevent_req_post(req
, ev
);
577 static void cli_api_pipe_trans_done(struct tevent_req
*subreq
)
579 struct tevent_req
*req
= tevent_req_callback_data(
580 subreq
, struct tevent_req
);
581 struct cli_api_pipe_state
*state
= tevent_req_data(
582 req
, struct cli_api_pipe_state
);
585 status
= state
->transport
->trans_recv(subreq
, state
, &state
->rdata
,
588 if (!NT_STATUS_IS_OK(status
)) {
589 tevent_req_nterror(req
, status
);
592 tevent_req_done(req
);
595 static void cli_api_pipe_write_done(struct tevent_req
*subreq
)
597 struct tevent_req
*req
= tevent_req_callback_data(
598 subreq
, struct tevent_req
);
599 struct cli_api_pipe_state
*state
= tevent_req_data(
600 req
, struct cli_api_pipe_state
);
603 status
= rpc_write_recv(subreq
);
605 if (!NT_STATUS_IS_OK(status
)) {
606 tevent_req_nterror(req
, status
);
610 state
->rdata
= talloc_array(state
, uint8_t, RPC_HEADER_LEN
);
611 if (tevent_req_nomem(state
->rdata
, req
)) {
616 * We don't need to use rpc_read_send here, the upper layer will cope
617 * with a short read, transport->trans_send could also return less
618 * than state->max_rdata_len.
620 subreq
= state
->transport
->read_send(state
, state
->ev
, state
->rdata
,
622 state
->transport
->priv
);
623 if (tevent_req_nomem(subreq
, req
)) {
626 tevent_req_set_callback(subreq
, cli_api_pipe_read_done
, req
);
629 static void cli_api_pipe_read_done(struct tevent_req
*subreq
)
631 struct tevent_req
*req
= tevent_req_callback_data(
632 subreq
, struct tevent_req
);
633 struct cli_api_pipe_state
*state
= tevent_req_data(
634 req
, struct cli_api_pipe_state
);
638 status
= state
->transport
->read_recv(subreq
, &received
);
640 if (!NT_STATUS_IS_OK(status
)) {
641 tevent_req_nterror(req
, status
);
644 state
->rdata_len
= received
;
645 tevent_req_done(req
);
648 static NTSTATUS
cli_api_pipe_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
649 uint8_t **prdata
, uint32_t *prdata_len
)
651 struct cli_api_pipe_state
*state
= tevent_req_data(
652 req
, struct cli_api_pipe_state
);
655 if (tevent_req_is_nterror(req
, &status
)) {
659 *prdata
= talloc_move(mem_ctx
, &state
->rdata
);
660 *prdata_len
= state
->rdata_len
;
664 /****************************************************************************
665 Send data on an rpc pipe via trans. The data must be the last
666 pdu fragment of an NDR data stream.
668 Receive response data from an rpc pipe, which may be large...
670 Read the first fragment: unfortunately have to use SMBtrans for the first
671 bit, then SMBreadX for subsequent bits.
673 If first fragment received also wasn't the last fragment, continue
674 getting fragments until we _do_ receive the last fragment.
676 Request/Response PDU's look like the following...
678 |<------------------PDU len----------------------------------------------->|
679 |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
681 +------------+-----------------+-------------+---------------+-------------+
682 | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA |
683 +------------+-----------------+-------------+---------------+-------------+
685 Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
686 signing & sealing being negotiated.
688 ****************************************************************************/
690 struct rpc_api_pipe_state
{
691 struct event_context
*ev
;
692 struct rpc_pipe_client
*cli
;
693 uint8_t expected_pkt_type
;
695 DATA_BLOB incoming_frag
;
696 struct ncacn_packet
*pkt
;
700 size_t reply_pdu_offset
;
704 static void rpc_api_pipe_trans_done(struct tevent_req
*subreq
);
705 static void rpc_api_pipe_got_pdu(struct tevent_req
*subreq
);
706 static void rpc_api_pipe_auth3_done(struct tevent_req
*subreq
);
708 static struct tevent_req
*rpc_api_pipe_send(TALLOC_CTX
*mem_ctx
,
709 struct event_context
*ev
,
710 struct rpc_pipe_client
*cli
,
711 DATA_BLOB
*data
, /* Outgoing PDU */
712 uint8_t expected_pkt_type
)
714 struct tevent_req
*req
, *subreq
;
715 struct rpc_api_pipe_state
*state
;
716 uint16_t max_recv_frag
;
719 req
= tevent_req_create(mem_ctx
, &state
, struct rpc_api_pipe_state
);
725 state
->expected_pkt_type
= expected_pkt_type
;
726 state
->incoming_frag
= data_blob_null
;
727 state
->reply_pdu
= data_blob_null
;
728 state
->reply_pdu_offset
= 0;
729 state
->endianess
= DCERPC_DREP_LE
;
732 * Ensure we're not sending too much.
734 if (data
->length
> cli
->max_xmit_frag
) {
735 status
= NT_STATUS_INVALID_PARAMETER
;
739 DEBUG(5,("rpc_api_pipe: %s\n", rpccli_pipe_txt(talloc_tos(), cli
)));
741 if (state
->expected_pkt_type
== DCERPC_PKT_AUTH3
) {
742 subreq
= rpc_write_send(state
, ev
, cli
->transport
,
743 data
->data
, data
->length
);
744 if (subreq
== NULL
) {
747 tevent_req_set_callback(subreq
, rpc_api_pipe_auth3_done
, req
);
751 /* get the header first, then fetch the rest once we have
752 * the frag_length available */
753 max_recv_frag
= RPC_HEADER_LEN
;
755 subreq
= cli_api_pipe_send(state
, ev
, cli
->transport
,
756 data
->data
, data
->length
, max_recv_frag
);
757 if (subreq
== NULL
) {
760 tevent_req_set_callback(subreq
, rpc_api_pipe_trans_done
, req
);
764 tevent_req_nterror(req
, status
);
765 return tevent_req_post(req
, ev
);
771 static void rpc_api_pipe_auth3_done(struct tevent_req
*subreq
)
773 struct tevent_req
*req
=
774 tevent_req_callback_data(subreq
,
778 status
= rpc_write_recv(subreq
);
780 if (!NT_STATUS_IS_OK(status
)) {
781 tevent_req_nterror(req
, status
);
785 tevent_req_done(req
);
788 static void rpc_api_pipe_trans_done(struct tevent_req
*subreq
)
790 struct tevent_req
*req
= tevent_req_callback_data(
791 subreq
, struct tevent_req
);
792 struct rpc_api_pipe_state
*state
= tevent_req_data(
793 req
, struct rpc_api_pipe_state
);
795 uint8_t *rdata
= NULL
;
796 uint32_t rdata_len
= 0;
798 status
= cli_api_pipe_recv(subreq
, state
, &rdata
, &rdata_len
);
800 if (!NT_STATUS_IS_OK(status
)) {
801 DEBUG(5, ("cli_api_pipe failed: %s\n", nt_errstr(status
)));
802 tevent_req_nterror(req
, status
);
807 DEBUG(3,("rpc_api_pipe: %s failed to return data.\n",
808 rpccli_pipe_txt(talloc_tos(), state
->cli
)));
809 tevent_req_done(req
);
814 * Move data on state->incoming_frag.
816 state
->incoming_frag
.data
= talloc_move(state
, &rdata
);
817 state
->incoming_frag
.length
= rdata_len
;
818 if (!state
->incoming_frag
.data
) {
819 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
823 /* Ensure we have enough data for a pdu. */
824 subreq
= get_complete_frag_send(state
, state
->ev
, state
->cli
,
825 &state
->incoming_frag
);
826 if (tevent_req_nomem(subreq
, req
)) {
829 tevent_req_set_callback(subreq
, rpc_api_pipe_got_pdu
, req
);
832 static void rpc_api_pipe_got_pdu(struct tevent_req
*subreq
)
834 struct tevent_req
*req
= tevent_req_callback_data(
835 subreq
, struct tevent_req
);
836 struct rpc_api_pipe_state
*state
= tevent_req_data(
837 req
, struct rpc_api_pipe_state
);
839 DATA_BLOB rdata
= data_blob_null
;
841 status
= get_complete_frag_recv(subreq
);
843 if (!NT_STATUS_IS_OK(status
)) {
844 DEBUG(5, ("get_complete_frag failed: %s\n",
846 tevent_req_nterror(req
, status
);
850 state
->pkt
= talloc(state
, struct ncacn_packet
);
852 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
856 status
= dcerpc_pull_ncacn_packet(state
->pkt
,
857 &state
->incoming_frag
,
860 if (!NT_STATUS_IS_OK(status
)) {
861 tevent_req_nterror(req
, status
);
865 if (state
->incoming_frag
.length
!= state
->pkt
->frag_length
) {
866 DEBUG(5, ("Incorrect pdu length %u, expected %u\n",
867 (unsigned int)state
->incoming_frag
.length
,
868 (unsigned int)state
->pkt
->frag_length
));
869 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
873 status
= cli_pipe_validate_current_pdu(state
,
874 state
->cli
, state
->pkt
,
875 &state
->incoming_frag
,
876 state
->expected_pkt_type
,
880 DEBUG(10,("rpc_api_pipe: got frag len of %u at offset %u: %s\n",
881 (unsigned)state
->incoming_frag
.length
,
882 (unsigned)state
->reply_pdu_offset
,
885 if (!NT_STATUS_IS_OK(status
)) {
886 tevent_req_nterror(req
, status
);
890 if ((state
->pkt
->pfc_flags
& DCERPC_PFC_FLAG_FIRST
)
891 && (state
->pkt
->drep
[0] != DCERPC_DREP_LE
)) {
893 * Set the data type correctly for big-endian data on the
896 DEBUG(10,("rpc_api_pipe: On %s PDU data format is "
898 rpccli_pipe_txt(talloc_tos(), state
->cli
)));
899 state
->endianess
= 0x00; /* BIG ENDIAN */
902 * Check endianness on subsequent packets.
904 if (state
->endianess
!= state
->pkt
->drep
[0]) {
905 DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to "
907 state
->endianess
?"little":"big",
908 state
->pkt
->drep
[0]?"little":"big"));
909 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
913 /* Now copy the data portion out of the pdu into rbuf. */
914 if (state
->reply_pdu
.length
< state
->reply_pdu_offset
+ rdata
.length
) {
915 if (!data_blob_realloc(NULL
, &state
->reply_pdu
,
916 state
->reply_pdu_offset
+ rdata
.length
)) {
917 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
922 memcpy(state
->reply_pdu
.data
+ state
->reply_pdu_offset
,
923 rdata
.data
, rdata
.length
);
924 state
->reply_pdu_offset
+= rdata
.length
;
926 /* reset state->incoming_frag, there is no need to free it,
927 * it will be reallocated to the right size the next time
929 state
->incoming_frag
.length
= 0;
931 if (state
->pkt
->pfc_flags
& DCERPC_PFC_FLAG_LAST
) {
932 /* make sure the pdu length is right now that we
933 * have all the data available (alloc hint may
934 * have allocated more than was actually used) */
935 state
->reply_pdu
.length
= state
->reply_pdu_offset
;
936 DEBUG(10,("rpc_api_pipe: %s returned %u bytes.\n",
937 rpccli_pipe_txt(talloc_tos(), state
->cli
),
938 (unsigned)state
->reply_pdu
.length
));
939 tevent_req_done(req
);
943 subreq
= get_complete_frag_send(state
, state
->ev
, state
->cli
,
944 &state
->incoming_frag
);
945 if (tevent_req_nomem(subreq
, req
)) {
948 tevent_req_set_callback(subreq
, rpc_api_pipe_got_pdu
, req
);
951 static NTSTATUS
rpc_api_pipe_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
952 struct ncacn_packet
**pkt
,
953 DATA_BLOB
*reply_pdu
)
955 struct rpc_api_pipe_state
*state
= tevent_req_data(
956 req
, struct rpc_api_pipe_state
);
959 if (tevent_req_is_nterror(req
, &status
)) {
963 /* return data to caller and assign it ownership of memory */
965 reply_pdu
->data
= talloc_move(mem_ctx
, &state
->reply_pdu
.data
);
966 reply_pdu
->length
= state
->reply_pdu
.length
;
967 state
->reply_pdu
.length
= 0;
969 data_blob_free(&state
->reply_pdu
);
973 *pkt
= talloc_steal(mem_ctx
, state
->pkt
);
979 /*******************************************************************
980 Creates spnego auth bind.
981 ********************************************************************/
983 static NTSTATUS
create_spnego_auth_bind_req(TALLOC_CTX
*mem_ctx
,
984 struct pipe_auth_data
*auth
,
985 DATA_BLOB
*auth_token
)
987 struct spnego_context
*spnego_ctx
;
988 DATA_BLOB in_token
= data_blob_null
;
991 spnego_ctx
= talloc_get_type_abort(auth
->auth_ctx
,
992 struct spnego_context
);
994 /* Negotiate the initial auth token */
995 status
= spnego_get_client_auth_token(mem_ctx
, spnego_ctx
,
996 &in_token
, auth_token
);
997 if (!NT_STATUS_IS_OK(status
)) {
1001 DEBUG(5, ("Created GSS Authentication Token:\n"));
1002 dump_data(5, auth_token
->data
, auth_token
->length
);
1004 return NT_STATUS_OK
;
1007 /*******************************************************************
1008 Creates krb5 auth bind.
1009 ********************************************************************/
1011 static NTSTATUS
create_gssapi_auth_bind_req(TALLOC_CTX
*mem_ctx
,
1012 struct pipe_auth_data
*auth
,
1013 DATA_BLOB
*auth_token
)
1015 struct gse_context
*gse_ctx
;
1016 DATA_BLOB in_token
= data_blob_null
;
1019 gse_ctx
= talloc_get_type_abort(auth
->auth_ctx
,
1020 struct gse_context
);
1022 /* Negotiate the initial auth token */
1023 status
= gse_get_client_auth_token(mem_ctx
, gse_ctx
,
1026 if (!NT_STATUS_IS_OK(status
)) {
1030 DEBUG(5, ("Created GSS Authentication Token:\n"));
1031 dump_data(5, auth_token
->data
, auth_token
->length
);
1033 return NT_STATUS_OK
;
1036 /*******************************************************************
1037 Creates NTLMSSP auth bind.
1038 ********************************************************************/
1040 static NTSTATUS
create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client
*cli
,
1041 TALLOC_CTX
*mem_ctx
,
1042 DATA_BLOB
*auth_token
)
1044 struct gensec_security
*gensec_security
;
1045 DATA_BLOB null_blob
= data_blob_null
;
1048 gensec_security
= talloc_get_type_abort(cli
->auth
->auth_ctx
,
1049 struct gensec_security
);
1051 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
1052 status
= gensec_update(gensec_security
, mem_ctx
, NULL
, null_blob
, auth_token
);
1054 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1055 data_blob_free(auth_token
);
1059 DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
1060 dump_data(5, auth_token
->data
, auth_token
->length
);
1062 return NT_STATUS_OK
;
1065 /*******************************************************************
1066 Creates schannel auth bind.
1067 ********************************************************************/
1069 static NTSTATUS
create_schannel_auth_rpc_bind_req(struct rpc_pipe_client
*cli
,
1070 DATA_BLOB
*auth_token
)
1073 struct NL_AUTH_MESSAGE r
;
1075 /* Use lp_workgroup() if domain not specified */
1077 if (!cli
->auth
->domain
|| !cli
->auth
->domain
[0]) {
1078 cli
->auth
->domain
= talloc_strdup(cli
, lp_workgroup());
1079 if (cli
->auth
->domain
== NULL
) {
1080 return NT_STATUS_NO_MEMORY
;
1085 * Now marshall the data into the auth parse_struct.
1088 r
.MessageType
= NL_NEGOTIATE_REQUEST
;
1089 r
.Flags
= NL_FLAG_OEM_NETBIOS_DOMAIN_NAME
|
1090 NL_FLAG_OEM_NETBIOS_COMPUTER_NAME
;
1091 r
.oem_netbios_domain
.a
= cli
->auth
->domain
;
1092 r
.oem_netbios_computer
.a
= lp_netbios_name();
1094 status
= dcerpc_push_schannel_bind(cli
, &r
, auth_token
);
1095 if (!NT_STATUS_IS_OK(status
)) {
1099 return NT_STATUS_OK
;
1102 /*******************************************************************
1103 Creates the internals of a DCE/RPC bind request or alter context PDU.
1104 ********************************************************************/
1106 static NTSTATUS
create_bind_or_alt_ctx_internal(TALLOC_CTX
*mem_ctx
,
1107 enum dcerpc_pkt_type ptype
,
1109 const struct ndr_syntax_id
*abstract
,
1110 const struct ndr_syntax_id
*transfer
,
1111 const DATA_BLOB
*auth_info
,
1114 uint16 auth_len
= auth_info
->length
;
1116 union dcerpc_payload u
;
1117 struct dcerpc_ctx_list ctx_list
;
1120 auth_len
-= DCERPC_AUTH_TRAILER_LENGTH
;
1123 ctx_list
.context_id
= 0;
1124 ctx_list
.num_transfer_syntaxes
= 1;
1125 ctx_list
.abstract_syntax
= *abstract
;
1126 ctx_list
.transfer_syntaxes
= (struct ndr_syntax_id
*)discard_const(transfer
);
1128 u
.bind
.max_xmit_frag
= RPC_MAX_PDU_FRAG_LEN
;
1129 u
.bind
.max_recv_frag
= RPC_MAX_PDU_FRAG_LEN
;
1130 u
.bind
.assoc_group_id
= 0x0;
1131 u
.bind
.num_contexts
= 1;
1132 u
.bind
.ctx_list
= &ctx_list
;
1133 u
.bind
.auth_info
= *auth_info
;
1135 status
= dcerpc_push_ncacn_packet(mem_ctx
,
1137 DCERPC_PFC_FLAG_FIRST
|
1138 DCERPC_PFC_FLAG_LAST
,
1143 if (!NT_STATUS_IS_OK(status
)) {
1144 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1148 return NT_STATUS_OK
;
1151 /*******************************************************************
1152 Creates a DCE/RPC bind request.
1153 ********************************************************************/
1155 static NTSTATUS
create_rpc_bind_req(TALLOC_CTX
*mem_ctx
,
1156 struct rpc_pipe_client
*cli
,
1157 struct pipe_auth_data
*auth
,
1159 const struct ndr_syntax_id
*abstract
,
1160 const struct ndr_syntax_id
*transfer
,
1163 DATA_BLOB auth_token
= data_blob_null
;
1164 DATA_BLOB auth_info
= data_blob_null
;
1165 NTSTATUS ret
= NT_STATUS_OK
;
1167 switch (auth
->auth_type
) {
1168 case DCERPC_AUTH_TYPE_SCHANNEL
:
1169 ret
= create_schannel_auth_rpc_bind_req(cli
, &auth_token
);
1170 if (!NT_STATUS_IS_OK(ret
)) {
1175 case DCERPC_AUTH_TYPE_NTLMSSP
:
1176 ret
= create_ntlmssp_auth_rpc_bind_req(cli
, mem_ctx
, &auth_token
);
1177 if (!NT_STATUS_IS_OK(ret
)) {
1182 case DCERPC_AUTH_TYPE_SPNEGO
:
1183 ret
= create_spnego_auth_bind_req(cli
, auth
, &auth_token
);
1184 if (!NT_STATUS_IS_OK(ret
)) {
1189 case DCERPC_AUTH_TYPE_KRB5
:
1190 ret
= create_gssapi_auth_bind_req(mem_ctx
, auth
, &auth_token
);
1191 if (!NT_STATUS_IS_OK(ret
)) {
1196 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM
:
1197 auth_token
= data_blob_talloc(mem_ctx
,
1198 "NCALRPC_AUTH_TOKEN",
1202 case DCERPC_AUTH_TYPE_NONE
:
1206 /* "Can't" happen. */
1207 return NT_STATUS_INVALID_INFO_CLASS
;
1210 if (auth_token
.length
!= 0) {
1211 ret
= dcerpc_push_dcerpc_auth(cli
,
1214 0, /* auth_pad_length */
1215 1, /* auth_context_id */
1218 if (!NT_STATUS_IS_OK(ret
)) {
1221 data_blob_free(&auth_token
);
1224 ret
= create_bind_or_alt_ctx_internal(mem_ctx
,
1234 /*******************************************************************
1236 Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
1237 Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
1238 and deals with signing/sealing details.
1239 ********************************************************************/
1241 struct rpc_api_pipe_req_state
{
1242 struct event_context
*ev
;
1243 struct rpc_pipe_client
*cli
;
1246 DATA_BLOB
*req_data
;
1247 uint32_t req_data_sent
;
1249 DATA_BLOB reply_pdu
;
1252 static void rpc_api_pipe_req_write_done(struct tevent_req
*subreq
);
1253 static void rpc_api_pipe_req_done(struct tevent_req
*subreq
);
1254 static NTSTATUS
prepare_next_frag(struct rpc_api_pipe_req_state
*state
,
1255 bool *is_last_frag
);
1257 struct tevent_req
*rpc_api_pipe_req_send(TALLOC_CTX
*mem_ctx
,
1258 struct event_context
*ev
,
1259 struct rpc_pipe_client
*cli
,
1261 DATA_BLOB
*req_data
)
1263 struct tevent_req
*req
, *subreq
;
1264 struct rpc_api_pipe_req_state
*state
;
1268 req
= tevent_req_create(mem_ctx
, &state
,
1269 struct rpc_api_pipe_req_state
);
1275 state
->op_num
= op_num
;
1276 state
->req_data
= req_data
;
1277 state
->req_data_sent
= 0;
1278 state
->call_id
= get_rpc_call_id();
1279 state
->reply_pdu
= data_blob_null
;
1280 state
->rpc_out
= data_blob_null
;
1282 if (cli
->max_xmit_frag
< DCERPC_REQUEST_LENGTH
1283 + RPC_MAX_SIGN_SIZE
) {
1284 /* Server is screwed up ! */
1285 status
= NT_STATUS_INVALID_PARAMETER
;
1289 status
= prepare_next_frag(state
, &is_last_frag
);
1290 if (!NT_STATUS_IS_OK(status
)) {
1295 subreq
= rpc_api_pipe_send(state
, ev
, state
->cli
,
1297 DCERPC_PKT_RESPONSE
);
1298 if (subreq
== NULL
) {
1301 tevent_req_set_callback(subreq
, rpc_api_pipe_req_done
, req
);
1303 subreq
= rpc_write_send(state
, ev
, cli
->transport
,
1304 state
->rpc_out
.data
,
1305 state
->rpc_out
.length
);
1306 if (subreq
== NULL
) {
1309 tevent_req_set_callback(subreq
, rpc_api_pipe_req_write_done
,
1315 tevent_req_nterror(req
, status
);
1316 return tevent_req_post(req
, ev
);
1322 static NTSTATUS
prepare_next_frag(struct rpc_api_pipe_req_state
*state
,
1325 size_t data_sent_thistime
;
1332 union dcerpc_payload u
;
1334 data_left
= state
->req_data
->length
- state
->req_data_sent
;
1336 status
= dcerpc_guess_sizes(state
->cli
->auth
,
1337 DCERPC_REQUEST_LENGTH
, data_left
,
1338 state
->cli
->max_xmit_frag
,
1339 CLIENT_NDR_PADDING_SIZE
,
1340 &data_sent_thistime
,
1341 &frag_len
, &auth_len
, &pad_len
);
1342 if (!NT_STATUS_IS_OK(status
)) {
1346 if (state
->req_data_sent
== 0) {
1347 flags
= DCERPC_PFC_FLAG_FIRST
;
1350 if (data_sent_thistime
== data_left
) {
1351 flags
|= DCERPC_PFC_FLAG_LAST
;
1354 data_blob_free(&state
->rpc_out
);
1356 ZERO_STRUCT(u
.request
);
1358 u
.request
.alloc_hint
= state
->req_data
->length
;
1359 u
.request
.context_id
= 0;
1360 u
.request
.opnum
= state
->op_num
;
1362 status
= dcerpc_push_ncacn_packet(state
,
1369 if (!NT_STATUS_IS_OK(status
)) {
1373 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
1374 * compute it right for requests because the auth trailer is missing
1376 dcerpc_set_frag_length(&state
->rpc_out
, frag_len
);
1378 /* Copy in the data. */
1379 if (!data_blob_append(NULL
, &state
->rpc_out
,
1380 state
->req_data
->data
+ state
->req_data_sent
,
1381 data_sent_thistime
)) {
1382 return NT_STATUS_NO_MEMORY
;
1385 switch (state
->cli
->auth
->auth_level
) {
1386 case DCERPC_AUTH_LEVEL_NONE
:
1387 case DCERPC_AUTH_LEVEL_CONNECT
:
1388 case DCERPC_AUTH_LEVEL_PACKET
:
1390 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1391 case DCERPC_AUTH_LEVEL_PRIVACY
:
1392 status
= dcerpc_add_auth_footer(state
->cli
->auth
, pad_len
,
1394 if (!NT_STATUS_IS_OK(status
)) {
1399 return NT_STATUS_INVALID_PARAMETER
;
1402 state
->req_data_sent
+= data_sent_thistime
;
1403 *is_last_frag
= ((flags
& DCERPC_PFC_FLAG_LAST
) != 0);
1408 static void rpc_api_pipe_req_write_done(struct tevent_req
*subreq
)
1410 struct tevent_req
*req
= tevent_req_callback_data(
1411 subreq
, struct tevent_req
);
1412 struct rpc_api_pipe_req_state
*state
= tevent_req_data(
1413 req
, struct rpc_api_pipe_req_state
);
1417 status
= rpc_write_recv(subreq
);
1418 TALLOC_FREE(subreq
);
1419 if (!NT_STATUS_IS_OK(status
)) {
1420 tevent_req_nterror(req
, status
);
1424 status
= prepare_next_frag(state
, &is_last_frag
);
1425 if (!NT_STATUS_IS_OK(status
)) {
1426 tevent_req_nterror(req
, status
);
1431 subreq
= rpc_api_pipe_send(state
, state
->ev
, state
->cli
,
1433 DCERPC_PKT_RESPONSE
);
1434 if (tevent_req_nomem(subreq
, req
)) {
1437 tevent_req_set_callback(subreq
, rpc_api_pipe_req_done
, req
);
1439 subreq
= rpc_write_send(state
, state
->ev
,
1440 state
->cli
->transport
,
1441 state
->rpc_out
.data
,
1442 state
->rpc_out
.length
);
1443 if (tevent_req_nomem(subreq
, req
)) {
1446 tevent_req_set_callback(subreq
, rpc_api_pipe_req_write_done
,
1451 static void rpc_api_pipe_req_done(struct tevent_req
*subreq
)
1453 struct tevent_req
*req
= tevent_req_callback_data(
1454 subreq
, struct tevent_req
);
1455 struct rpc_api_pipe_req_state
*state
= tevent_req_data(
1456 req
, struct rpc_api_pipe_req_state
);
1459 status
= rpc_api_pipe_recv(subreq
, state
, NULL
, &state
->reply_pdu
);
1460 TALLOC_FREE(subreq
);
1461 if (!NT_STATUS_IS_OK(status
)) {
1462 tevent_req_nterror(req
, status
);
1465 tevent_req_done(req
);
1468 NTSTATUS
rpc_api_pipe_req_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
1469 DATA_BLOB
*reply_pdu
)
1471 struct rpc_api_pipe_req_state
*state
= tevent_req_data(
1472 req
, struct rpc_api_pipe_req_state
);
1475 if (tevent_req_is_nterror(req
, &status
)) {
1477 * We always have to initialize to reply pdu, even if there is
1478 * none. The rpccli_* caller routines expect this.
1480 *reply_pdu
= data_blob_null
;
1484 /* return data to caller and assign it ownership of memory */
1485 reply_pdu
->data
= talloc_move(mem_ctx
, &state
->reply_pdu
.data
);
1486 reply_pdu
->length
= state
->reply_pdu
.length
;
1487 state
->reply_pdu
.length
= 0;
1489 return NT_STATUS_OK
;
1492 /****************************************************************************
1493 Check the rpc bind acknowledge response.
1494 ****************************************************************************/
1496 static bool check_bind_response(const struct dcerpc_bind_ack
*r
,
1497 const struct ndr_syntax_id
*transfer
)
1499 struct dcerpc_ack_ctx ctx
;
1501 if (r
->secondary_address_size
== 0) {
1502 DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
1505 if (r
->num_results
< 1 || !r
->ctx_list
) {
1509 ctx
= r
->ctx_list
[0];
1511 /* check the transfer syntax */
1512 if ((ctx
.syntax
.if_version
!= transfer
->if_version
) ||
1513 (memcmp(&ctx
.syntax
.uuid
, &transfer
->uuid
, sizeof(transfer
->uuid
)) !=0)) {
1514 DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
1518 if (r
->num_results
!= 0x1 || ctx
.result
!= 0) {
1519 DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
1520 r
->num_results
, ctx
.reason
));
1523 DEBUG(5,("check_bind_response: accepted!\n"));
1527 /*******************************************************************
1528 Creates a DCE/RPC bind authentication response.
1529 This is the packet that is sent back to the server once we
1530 have received a BIND-ACK, to finish the third leg of
1531 the authentication handshake.
1532 ********************************************************************/
1534 static NTSTATUS
create_rpc_bind_auth3(TALLOC_CTX
*mem_ctx
,
1535 struct rpc_pipe_client
*cli
,
1537 enum dcerpc_AuthType auth_type
,
1538 enum dcerpc_AuthLevel auth_level
,
1539 DATA_BLOB
*pauth_blob
,
1543 union dcerpc_payload u
;
1547 status
= dcerpc_push_dcerpc_auth(mem_ctx
,
1550 0, /* auth_pad_length */
1551 1, /* auth_context_id */
1553 &u
.auth3
.auth_info
);
1554 if (!NT_STATUS_IS_OK(status
)) {
1558 status
= dcerpc_push_ncacn_packet(mem_ctx
,
1560 DCERPC_PFC_FLAG_FIRST
|
1561 DCERPC_PFC_FLAG_LAST
,
1566 data_blob_free(&u
.auth3
.auth_info
);
1567 if (!NT_STATUS_IS_OK(status
)) {
1568 DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
1572 return NT_STATUS_OK
;
1575 /*******************************************************************
1576 Creates a DCE/RPC bind alter context authentication request which
1577 may contain a spnego auth blobl
1578 ********************************************************************/
1580 static NTSTATUS
create_rpc_alter_context(TALLOC_CTX
*mem_ctx
,
1581 enum dcerpc_AuthType auth_type
,
1582 enum dcerpc_AuthLevel auth_level
,
1584 const struct ndr_syntax_id
*abstract
,
1585 const struct ndr_syntax_id
*transfer
,
1586 const DATA_BLOB
*pauth_blob
, /* spnego auth blob already created. */
1589 DATA_BLOB auth_info
;
1592 status
= dcerpc_push_dcerpc_auth(mem_ctx
,
1595 0, /* auth_pad_length */
1596 1, /* auth_context_id */
1599 if (!NT_STATUS_IS_OK(status
)) {
1603 status
= create_bind_or_alt_ctx_internal(mem_ctx
,
1610 data_blob_free(&auth_info
);
1614 /****************************************************************************
1616 ****************************************************************************/
1618 struct rpc_pipe_bind_state
{
1619 struct event_context
*ev
;
1620 struct rpc_pipe_client
*cli
;
1623 uint32_t rpc_call_id
;
1626 static void rpc_pipe_bind_step_one_done(struct tevent_req
*subreq
);
1627 static NTSTATUS
rpc_bind_next_send(struct tevent_req
*req
,
1628 struct rpc_pipe_bind_state
*state
,
1629 DATA_BLOB
*credentials
);
1630 static NTSTATUS
rpc_bind_finish_send(struct tevent_req
*req
,
1631 struct rpc_pipe_bind_state
*state
,
1632 DATA_BLOB
*credentials
);
1634 struct tevent_req
*rpc_pipe_bind_send(TALLOC_CTX
*mem_ctx
,
1635 struct event_context
*ev
,
1636 struct rpc_pipe_client
*cli
,
1637 struct pipe_auth_data
*auth
)
1639 struct tevent_req
*req
, *subreq
;
1640 struct rpc_pipe_bind_state
*state
;
1643 req
= tevent_req_create(mem_ctx
, &state
, struct rpc_pipe_bind_state
);
1648 DEBUG(5,("Bind RPC Pipe: %s auth_type %u, auth_level %u\n",
1649 rpccli_pipe_txt(talloc_tos(), cli
),
1650 (unsigned int)auth
->auth_type
,
1651 (unsigned int)auth
->auth_level
));
1655 state
->rpc_call_id
= get_rpc_call_id();
1657 cli
->auth
= talloc_move(cli
, &auth
);
1659 /* Marshall the outgoing data. */
1660 status
= create_rpc_bind_req(state
, cli
,
1663 &cli
->abstract_syntax
,
1664 &cli
->transfer_syntax
,
1667 if (!NT_STATUS_IS_OK(status
)) {
1671 subreq
= rpc_api_pipe_send(state
, ev
, cli
, &state
->rpc_out
,
1672 DCERPC_PKT_BIND_ACK
);
1673 if (subreq
== NULL
) {
1676 tevent_req_set_callback(subreq
, rpc_pipe_bind_step_one_done
, req
);
1680 tevent_req_nterror(req
, status
);
1681 return tevent_req_post(req
, ev
);
1687 static void rpc_pipe_bind_step_one_done(struct tevent_req
*subreq
)
1689 struct tevent_req
*req
= tevent_req_callback_data(
1690 subreq
, struct tevent_req
);
1691 struct rpc_pipe_bind_state
*state
= tevent_req_data(
1692 req
, struct rpc_pipe_bind_state
);
1693 struct pipe_auth_data
*pauth
= state
->cli
->auth
;
1694 struct gensec_security
*gensec_security
;
1695 struct spnego_context
*spnego_ctx
;
1696 struct gse_context
*gse_ctx
;
1697 struct ncacn_packet
*pkt
= NULL
;
1698 struct dcerpc_auth auth
;
1699 DATA_BLOB auth_token
= data_blob_null
;
1702 status
= rpc_api_pipe_recv(subreq
, talloc_tos(), &pkt
, NULL
);
1703 TALLOC_FREE(subreq
);
1704 if (!NT_STATUS_IS_OK(status
)) {
1705 DEBUG(3, ("rpc_pipe_bind: %s bind request returned %s\n",
1706 rpccli_pipe_txt(talloc_tos(), state
->cli
),
1707 nt_errstr(status
)));
1708 tevent_req_nterror(req
, status
);
1713 tevent_req_done(req
);
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_NCALRPC_AS_SYSTEM
:
1730 case DCERPC_AUTH_TYPE_SCHANNEL
:
1731 /* Bind complete. */
1732 tevent_req_done(req
);
1735 case DCERPC_AUTH_TYPE_NTLMSSP
:
1736 case DCERPC_AUTH_TYPE_SPNEGO
:
1737 case DCERPC_AUTH_TYPE_KRB5
:
1738 /* Paranoid lenght checks */
1739 if (pkt
->frag_length
< DCERPC_AUTH_TRAILER_LENGTH
1740 + pkt
->auth_length
) {
1741 tevent_req_nterror(req
,
1742 NT_STATUS_INFO_LENGTH_MISMATCH
);
1745 /* get auth credentials */
1746 status
= dcerpc_pull_dcerpc_auth(talloc_tos(),
1747 &pkt
->u
.bind_ack
.auth_info
,
1749 if (!NT_STATUS_IS_OK(status
)) {
1750 DEBUG(0, ("Failed to pull dcerpc auth: %s.\n",
1751 nt_errstr(status
)));
1752 tevent_req_nterror(req
, status
);
1762 * For authenticated binds we may need to do 3 or 4 leg binds.
1765 switch(pauth
->auth_type
) {
1767 case DCERPC_AUTH_TYPE_NONE
:
1768 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM
:
1769 case DCERPC_AUTH_TYPE_SCHANNEL
:
1770 /* Bind complete. */
1771 tevent_req_done(req
);
1774 case DCERPC_AUTH_TYPE_NTLMSSP
:
1775 gensec_security
= talloc_get_type_abort(pauth
->auth_ctx
,
1776 struct gensec_security
);
1777 status
= gensec_update(gensec_security
, state
, NULL
,
1778 auth
.credentials
, &auth_token
);
1779 if (NT_STATUS_EQUAL(status
,
1780 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1781 status
= rpc_bind_next_send(req
, state
,
1783 } else if (NT_STATUS_IS_OK(status
)) {
1784 status
= rpc_bind_finish_send(req
, state
,
1789 case DCERPC_AUTH_TYPE_SPNEGO
:
1790 spnego_ctx
= talloc_get_type_abort(pauth
->auth_ctx
,
1791 struct spnego_context
);
1792 status
= spnego_get_client_auth_token(state
,
1796 if (!NT_STATUS_IS_OK(status
)) {
1799 if (auth_token
.length
== 0) {
1800 /* Bind complete. */
1801 tevent_req_done(req
);
1804 if (spnego_require_more_processing(spnego_ctx
)) {
1805 status
= rpc_bind_next_send(req
, state
,
1808 status
= rpc_bind_finish_send(req
, state
,
1813 case DCERPC_AUTH_TYPE_KRB5
:
1814 gse_ctx
= talloc_get_type_abort(pauth
->auth_ctx
,
1815 struct gse_context
);
1816 status
= gse_get_client_auth_token(state
,
1820 if (!NT_STATUS_IS_OK(status
)) {
1824 if (gse_require_more_processing(gse_ctx
)) {
1825 status
= rpc_bind_next_send(req
, state
, &auth_token
);
1827 status
= rpc_bind_finish_send(req
, state
, &auth_token
);
1835 if (!NT_STATUS_IS_OK(status
)) {
1836 tevent_req_nterror(req
, status
);
1841 DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
1842 (unsigned int)state
->cli
->auth
->auth_type
));
1843 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
1846 static NTSTATUS
rpc_bind_next_send(struct tevent_req
*req
,
1847 struct rpc_pipe_bind_state
*state
,
1848 DATA_BLOB
*auth_token
)
1850 struct pipe_auth_data
*auth
= state
->cli
->auth
;
1851 struct tevent_req
*subreq
;
1854 /* Now prepare the alter context pdu. */
1855 data_blob_free(&state
->rpc_out
);
1857 status
= create_rpc_alter_context(state
,
1861 &state
->cli
->abstract_syntax
,
1862 &state
->cli
->transfer_syntax
,
1865 if (!NT_STATUS_IS_OK(status
)) {
1869 subreq
= rpc_api_pipe_send(state
, state
->ev
, state
->cli
,
1870 &state
->rpc_out
, DCERPC_PKT_ALTER_RESP
);
1871 if (subreq
== NULL
) {
1872 return NT_STATUS_NO_MEMORY
;
1874 tevent_req_set_callback(subreq
, rpc_pipe_bind_step_one_done
, req
);
1875 return NT_STATUS_OK
;
1878 static NTSTATUS
rpc_bind_finish_send(struct tevent_req
*req
,
1879 struct rpc_pipe_bind_state
*state
,
1880 DATA_BLOB
*auth_token
)
1882 struct pipe_auth_data
*auth
= state
->cli
->auth
;
1883 struct tevent_req
*subreq
;
1886 state
->auth3
= true;
1888 /* Now prepare the auth3 context pdu. */
1889 data_blob_free(&state
->rpc_out
);
1891 status
= create_rpc_bind_auth3(state
, state
->cli
,
1897 if (!NT_STATUS_IS_OK(status
)) {
1901 subreq
= rpc_api_pipe_send(state
, state
->ev
, state
->cli
,
1902 &state
->rpc_out
, DCERPC_PKT_AUTH3
);
1903 if (subreq
== NULL
) {
1904 return NT_STATUS_NO_MEMORY
;
1906 tevent_req_set_callback(subreq
, rpc_pipe_bind_step_one_done
, req
);
1907 return NT_STATUS_OK
;
1910 NTSTATUS
rpc_pipe_bind_recv(struct tevent_req
*req
)
1912 return tevent_req_simple_recv_ntstatus(req
);
1915 NTSTATUS
rpc_pipe_bind(struct rpc_pipe_client
*cli
,
1916 struct pipe_auth_data
*auth
)
1918 TALLOC_CTX
*frame
= talloc_stackframe();
1919 struct event_context
*ev
;
1920 struct tevent_req
*req
;
1921 NTSTATUS status
= NT_STATUS_OK
;
1923 ev
= event_context_init(frame
);
1925 status
= NT_STATUS_NO_MEMORY
;
1929 req
= rpc_pipe_bind_send(frame
, ev
, cli
, auth
);
1931 status
= NT_STATUS_NO_MEMORY
;
1935 if (!tevent_req_poll(req
, ev
)) {
1936 status
= map_nt_error_from_unix(errno
);
1940 status
= rpc_pipe_bind_recv(req
);
1946 #define RPCCLI_DEFAULT_TIMEOUT 10000 /* 10 seconds. */
1948 unsigned int rpccli_set_timeout(struct rpc_pipe_client
*rpc_cli
,
1949 unsigned int timeout
)
1953 if (rpc_cli
->transport
== NULL
) {
1954 return RPCCLI_DEFAULT_TIMEOUT
;
1957 if (rpc_cli
->transport
->set_timeout
== NULL
) {
1958 return RPCCLI_DEFAULT_TIMEOUT
;
1961 old
= rpc_cli
->transport
->set_timeout(rpc_cli
->transport
->priv
, timeout
);
1963 return RPCCLI_DEFAULT_TIMEOUT
;
1969 bool rpccli_is_connected(struct rpc_pipe_client
*rpc_cli
)
1971 if (rpc_cli
== NULL
) {
1975 if (rpc_cli
->transport
== NULL
) {
1979 return rpc_cli
->transport
->is_connected(rpc_cli
->transport
->priv
);
1982 struct rpccli_bh_state
{
1983 struct rpc_pipe_client
*rpc_cli
;
1986 static bool rpccli_bh_is_connected(struct dcerpc_binding_handle
*h
)
1988 struct rpccli_bh_state
*hs
= dcerpc_binding_handle_data(h
,
1989 struct rpccli_bh_state
);
1991 return rpccli_is_connected(hs
->rpc_cli
);
1994 static uint32_t rpccli_bh_set_timeout(struct dcerpc_binding_handle
*h
,
1997 struct rpccli_bh_state
*hs
= dcerpc_binding_handle_data(h
,
1998 struct rpccli_bh_state
);
2000 return rpccli_set_timeout(hs
->rpc_cli
, timeout
);
2003 struct rpccli_bh_raw_call_state
{
2009 static void rpccli_bh_raw_call_done(struct tevent_req
*subreq
);
2011 static struct tevent_req
*rpccli_bh_raw_call_send(TALLOC_CTX
*mem_ctx
,
2012 struct tevent_context
*ev
,
2013 struct dcerpc_binding_handle
*h
,
2014 const struct GUID
*object
,
2017 const uint8_t *in_data
,
2020 struct rpccli_bh_state
*hs
= dcerpc_binding_handle_data(h
,
2021 struct rpccli_bh_state
);
2022 struct tevent_req
*req
;
2023 struct rpccli_bh_raw_call_state
*state
;
2025 struct tevent_req
*subreq
;
2027 req
= tevent_req_create(mem_ctx
, &state
,
2028 struct rpccli_bh_raw_call_state
);
2032 state
->in_data
.data
= discard_const_p(uint8_t, in_data
);
2033 state
->in_data
.length
= in_length
;
2035 ok
= rpccli_bh_is_connected(h
);
2037 tevent_req_nterror(req
, NT_STATUS_CONNECTION_DISCONNECTED
);
2038 return tevent_req_post(req
, ev
);
2041 subreq
= rpc_api_pipe_req_send(state
, ev
, hs
->rpc_cli
,
2042 opnum
, &state
->in_data
);
2043 if (tevent_req_nomem(subreq
, req
)) {
2044 return tevent_req_post(req
, ev
);
2046 tevent_req_set_callback(subreq
, rpccli_bh_raw_call_done
, req
);
2051 static void rpccli_bh_raw_call_done(struct tevent_req
*subreq
)
2053 struct tevent_req
*req
=
2054 tevent_req_callback_data(subreq
,
2056 struct rpccli_bh_raw_call_state
*state
=
2057 tevent_req_data(req
,
2058 struct rpccli_bh_raw_call_state
);
2061 state
->out_flags
= 0;
2063 /* TODO: support bigendian responses */
2065 status
= rpc_api_pipe_req_recv(subreq
, state
, &state
->out_data
);
2066 TALLOC_FREE(subreq
);
2067 if (!NT_STATUS_IS_OK(status
)) {
2068 tevent_req_nterror(req
, status
);
2072 tevent_req_done(req
);
2075 static NTSTATUS
rpccli_bh_raw_call_recv(struct tevent_req
*req
,
2076 TALLOC_CTX
*mem_ctx
,
2079 uint32_t *out_flags
)
2081 struct rpccli_bh_raw_call_state
*state
=
2082 tevent_req_data(req
,
2083 struct rpccli_bh_raw_call_state
);
2086 if (tevent_req_is_nterror(req
, &status
)) {
2087 tevent_req_received(req
);
2091 *out_data
= talloc_move(mem_ctx
, &state
->out_data
.data
);
2092 *out_length
= state
->out_data
.length
;
2093 *out_flags
= state
->out_flags
;
2094 tevent_req_received(req
);
2095 return NT_STATUS_OK
;
2098 struct rpccli_bh_disconnect_state
{
2102 static struct tevent_req
*rpccli_bh_disconnect_send(TALLOC_CTX
*mem_ctx
,
2103 struct tevent_context
*ev
,
2104 struct dcerpc_binding_handle
*h
)
2106 struct rpccli_bh_state
*hs
= dcerpc_binding_handle_data(h
,
2107 struct rpccli_bh_state
);
2108 struct tevent_req
*req
;
2109 struct rpccli_bh_disconnect_state
*state
;
2112 req
= tevent_req_create(mem_ctx
, &state
,
2113 struct rpccli_bh_disconnect_state
);
2118 ok
= rpccli_bh_is_connected(h
);
2120 tevent_req_nterror(req
, NT_STATUS_CONNECTION_DISCONNECTED
);
2121 return tevent_req_post(req
, ev
);
2125 * TODO: do a real async disconnect ...
2127 * For now the caller needs to free rpc_cli
2131 tevent_req_done(req
);
2132 return tevent_req_post(req
, ev
);
2135 static NTSTATUS
rpccli_bh_disconnect_recv(struct tevent_req
*req
)
2139 if (tevent_req_is_nterror(req
, &status
)) {
2140 tevent_req_received(req
);
2144 tevent_req_received(req
);
2145 return NT_STATUS_OK
;
2148 static bool rpccli_bh_ref_alloc(struct dcerpc_binding_handle
*h
)
2153 static void rpccli_bh_do_ndr_print(struct dcerpc_binding_handle
*h
,
2155 const void *_struct_ptr
,
2156 const struct ndr_interface_call
*call
)
2158 void *struct_ptr
= discard_const(_struct_ptr
);
2160 if (DEBUGLEVEL
< 10) {
2164 if (ndr_flags
& NDR_IN
) {
2165 ndr_print_function_debug(call
->ndr_print
,
2170 if (ndr_flags
& NDR_OUT
) {
2171 ndr_print_function_debug(call
->ndr_print
,
2178 static const struct dcerpc_binding_handle_ops rpccli_bh_ops
= {
2180 .is_connected
= rpccli_bh_is_connected
,
2181 .set_timeout
= rpccli_bh_set_timeout
,
2182 .raw_call_send
= rpccli_bh_raw_call_send
,
2183 .raw_call_recv
= rpccli_bh_raw_call_recv
,
2184 .disconnect_send
= rpccli_bh_disconnect_send
,
2185 .disconnect_recv
= rpccli_bh_disconnect_recv
,
2187 .ref_alloc
= rpccli_bh_ref_alloc
,
2188 .do_ndr_print
= rpccli_bh_do_ndr_print
,
2191 /* initialise a rpc_pipe_client binding handle */
2192 struct dcerpc_binding_handle
*rpccli_bh_create(struct rpc_pipe_client
*c
)
2194 struct dcerpc_binding_handle
*h
;
2195 struct rpccli_bh_state
*hs
;
2197 h
= dcerpc_binding_handle_create(c
,
2202 struct rpccli_bh_state
,
2212 NTSTATUS
rpccli_ncalrpc_bind_data(TALLOC_CTX
*mem_ctx
,
2213 struct pipe_auth_data
**presult
)
2215 struct pipe_auth_data
*result
;
2217 result
= talloc(mem_ctx
, struct pipe_auth_data
);
2218 if (result
== NULL
) {
2219 return NT_STATUS_NO_MEMORY
;
2222 result
->auth_type
= DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM
;
2223 result
->auth_level
= DCERPC_AUTH_LEVEL_CONNECT
;
2225 result
->user_name
= talloc_strdup(result
, "");
2226 result
->domain
= talloc_strdup(result
, "");
2227 if ((result
->user_name
== NULL
) || (result
->domain
== NULL
)) {
2228 TALLOC_FREE(result
);
2229 return NT_STATUS_NO_MEMORY
;
2233 return NT_STATUS_OK
;
2236 NTSTATUS
rpccli_anon_bind_data(TALLOC_CTX
*mem_ctx
,
2237 struct pipe_auth_data
**presult
)
2239 struct pipe_auth_data
*result
;
2241 result
= talloc(mem_ctx
, struct pipe_auth_data
);
2242 if (result
== NULL
) {
2243 return NT_STATUS_NO_MEMORY
;
2246 result
->auth_type
= DCERPC_AUTH_TYPE_NONE
;
2247 result
->auth_level
= DCERPC_AUTH_LEVEL_NONE
;
2249 result
->user_name
= talloc_strdup(result
, "");
2250 result
->domain
= talloc_strdup(result
, "");
2251 if ((result
->user_name
== NULL
) || (result
->domain
== NULL
)) {
2252 TALLOC_FREE(result
);
2253 return NT_STATUS_NO_MEMORY
;
2257 return NT_STATUS_OK
;
2260 static NTSTATUS
rpccli_ntlmssp_bind_data(TALLOC_CTX
*mem_ctx
,
2261 enum dcerpc_AuthType auth_type
,
2262 enum dcerpc_AuthLevel auth_level
,
2264 const char *username
,
2265 const char *password
,
2266 struct pipe_auth_data
**presult
)
2268 struct auth_ntlmssp_state
*ntlmssp_ctx
;
2269 struct pipe_auth_data
*result
;
2272 result
= talloc(mem_ctx
, struct pipe_auth_data
);
2273 if (result
== NULL
) {
2274 return NT_STATUS_NO_MEMORY
;
2277 result
->auth_type
= auth_type
;
2278 result
->auth_level
= auth_level
;
2280 result
->user_name
= talloc_strdup(result
, username
);
2281 result
->domain
= talloc_strdup(result
, domain
);
2282 if ((result
->user_name
== NULL
) || (result
->domain
== NULL
)) {
2283 status
= NT_STATUS_NO_MEMORY
;
2287 status
= auth_ntlmssp_client_prepare(result
,
2289 if (!NT_STATUS_IS_OK(status
)) {
2293 status
= auth_ntlmssp_set_username(ntlmssp_ctx
, username
);
2294 if (!NT_STATUS_IS_OK(status
)) {
2298 status
= auth_ntlmssp_set_domain(ntlmssp_ctx
, domain
);
2299 if (!NT_STATUS_IS_OK(status
)) {
2303 status
= auth_ntlmssp_set_password(ntlmssp_ctx
, password
);
2304 if (!NT_STATUS_IS_OK(status
)) {
2308 if (auth_level
== DCERPC_AUTH_LEVEL_INTEGRITY
) {
2309 gensec_want_feature(ntlmssp_ctx
->gensec_security
, GENSEC_FEATURE_SIGN
);
2310 } else if (auth_level
== DCERPC_AUTH_LEVEL_PRIVACY
) {
2311 gensec_want_feature(ntlmssp_ctx
->gensec_security
, GENSEC_FEATURE_SEAL
);
2314 status
= auth_ntlmssp_client_start(ntlmssp_ctx
);
2315 if (!NT_STATUS_IS_OK(status
)) {
2319 result
->auth_ctx
= talloc_move(result
, &ntlmssp_ctx
->gensec_security
);
2320 talloc_free(ntlmssp_ctx
);
2322 return NT_STATUS_OK
;
2325 TALLOC_FREE(result
);
2329 NTSTATUS
rpccli_schannel_bind_data(TALLOC_CTX
*mem_ctx
, const char *domain
,
2330 enum dcerpc_AuthLevel auth_level
,
2331 struct netlogon_creds_CredentialState
*creds
,
2332 struct pipe_auth_data
**presult
)
2334 struct schannel_state
*schannel_auth
;
2335 struct pipe_auth_data
*result
;
2337 result
= talloc(mem_ctx
, struct pipe_auth_data
);
2338 if (result
== NULL
) {
2339 return NT_STATUS_NO_MEMORY
;
2342 result
->auth_type
= DCERPC_AUTH_TYPE_SCHANNEL
;
2343 result
->auth_level
= auth_level
;
2345 result
->user_name
= talloc_strdup(result
, "");
2346 result
->domain
= talloc_strdup(result
, domain
);
2347 if ((result
->user_name
== NULL
) || (result
->domain
== NULL
)) {
2351 schannel_auth
= talloc(result
, struct schannel_state
);
2352 if (schannel_auth
== NULL
) {
2356 schannel_auth
->state
= SCHANNEL_STATE_START
;
2357 schannel_auth
->seq_num
= 0;
2358 schannel_auth
->initiator
= true;
2359 schannel_auth
->creds
= netlogon_creds_copy(result
, creds
);
2361 result
->auth_ctx
= schannel_auth
;
2363 return NT_STATUS_OK
;
2366 TALLOC_FREE(result
);
2367 return NT_STATUS_NO_MEMORY
;
2371 * Create an rpc pipe client struct, connecting to a tcp port.
2373 static NTSTATUS
rpc_pipe_open_tcp_port(TALLOC_CTX
*mem_ctx
, const char *host
,
2375 const struct ndr_syntax_id
*abstract_syntax
,
2376 struct rpc_pipe_client
**presult
)
2378 struct rpc_pipe_client
*result
;
2379 struct sockaddr_storage addr
;
2383 result
= talloc_zero(mem_ctx
, struct rpc_pipe_client
);
2384 if (result
== NULL
) {
2385 return NT_STATUS_NO_MEMORY
;
2388 result
->abstract_syntax
= *abstract_syntax
;
2389 result
->transfer_syntax
= ndr_transfer_syntax
;
2391 result
->desthost
= talloc_strdup(result
, host
);
2392 result
->srv_name_slash
= talloc_asprintf_strupper_m(
2393 result
, "\\\\%s", result
->desthost
);
2394 if ((result
->desthost
== NULL
) || (result
->srv_name_slash
== NULL
)) {
2395 status
= NT_STATUS_NO_MEMORY
;
2399 result
->max_xmit_frag
= RPC_MAX_PDU_FRAG_LEN
;
2400 result
->max_recv_frag
= RPC_MAX_PDU_FRAG_LEN
;
2402 if (!resolve_name(host
, &addr
, 0, false)) {
2403 status
= NT_STATUS_NOT_FOUND
;
2407 status
= open_socket_out(&addr
, port
, 60*1000, &fd
);
2408 if (!NT_STATUS_IS_OK(status
)) {
2411 set_socket_options(fd
, lp_socket_options());
2413 status
= rpc_transport_sock_init(result
, fd
, &result
->transport
);
2414 if (!NT_STATUS_IS_OK(status
)) {
2419 result
->transport
->transport
= NCACN_IP_TCP
;
2421 result
->binding_handle
= rpccli_bh_create(result
);
2422 if (result
->binding_handle
== NULL
) {
2423 TALLOC_FREE(result
);
2424 return NT_STATUS_NO_MEMORY
;
2428 return NT_STATUS_OK
;
2431 TALLOC_FREE(result
);
2436 * Determine the tcp port on which a dcerpc interface is listening
2437 * for the ncacn_ip_tcp transport via the endpoint mapper of the
2440 static NTSTATUS
rpc_pipe_get_tcp_port(const char *host
,
2441 const struct ndr_syntax_id
*abstract_syntax
,
2445 struct rpc_pipe_client
*epm_pipe
= NULL
;
2446 struct dcerpc_binding_handle
*epm_handle
= NULL
;
2447 struct pipe_auth_data
*auth
= NULL
;
2448 struct dcerpc_binding
*map_binding
= NULL
;
2449 struct dcerpc_binding
*res_binding
= NULL
;
2450 struct epm_twr_t
*map_tower
= NULL
;
2451 struct epm_twr_t
*res_towers
= NULL
;
2452 struct policy_handle
*entry_handle
= NULL
;
2453 uint32_t num_towers
= 0;
2454 uint32_t max_towers
= 1;
2455 struct epm_twr_p_t towers
;
2456 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2457 uint32_t result
= 0;
2459 if (pport
== NULL
) {
2460 status
= NT_STATUS_INVALID_PARAMETER
;
2464 if (ndr_syntax_id_equal(abstract_syntax
,
2465 &ndr_table_epmapper
.syntax_id
)) {
2467 return NT_STATUS_OK
;
2470 /* open the connection to the endpoint mapper */
2471 status
= rpc_pipe_open_tcp_port(tmp_ctx
, host
, 135,
2472 &ndr_table_epmapper
.syntax_id
,
2475 if (!NT_STATUS_IS_OK(status
)) {
2478 epm_handle
= epm_pipe
->binding_handle
;
2480 status
= rpccli_anon_bind_data(tmp_ctx
, &auth
);
2481 if (!NT_STATUS_IS_OK(status
)) {
2485 status
= rpc_pipe_bind(epm_pipe
, auth
);
2486 if (!NT_STATUS_IS_OK(status
)) {
2490 /* create tower for asking the epmapper */
2492 map_binding
= talloc_zero(tmp_ctx
, struct dcerpc_binding
);
2493 if (map_binding
== NULL
) {
2494 status
= NT_STATUS_NO_MEMORY
;
2498 map_binding
->transport
= NCACN_IP_TCP
;
2499 map_binding
->object
= *abstract_syntax
;
2500 map_binding
->host
= host
; /* needed? */
2501 map_binding
->endpoint
= "0"; /* correct? needed? */
2503 map_tower
= talloc_zero(tmp_ctx
, struct epm_twr_t
);
2504 if (map_tower
== NULL
) {
2505 status
= NT_STATUS_NO_MEMORY
;
2509 status
= dcerpc_binding_build_tower(tmp_ctx
, map_binding
,
2510 &(map_tower
->tower
));
2511 if (!NT_STATUS_IS_OK(status
)) {
2515 /* allocate further parameters for the epm_Map call */
2517 res_towers
= talloc_array(tmp_ctx
, struct epm_twr_t
, max_towers
);
2518 if (res_towers
== NULL
) {
2519 status
= NT_STATUS_NO_MEMORY
;
2522 towers
.twr
= res_towers
;
2524 entry_handle
= talloc_zero(tmp_ctx
, struct policy_handle
);
2525 if (entry_handle
== NULL
) {
2526 status
= NT_STATUS_NO_MEMORY
;
2530 /* ask the endpoint mapper for the port */
2532 status
= dcerpc_epm_Map(epm_handle
,
2534 discard_const_p(struct GUID
,
2535 &(abstract_syntax
->uuid
)),
2543 if (!NT_STATUS_IS_OK(status
)) {
2547 if (result
!= EPMAPPER_STATUS_OK
) {
2548 status
= NT_STATUS_UNSUCCESSFUL
;
2552 if (num_towers
!= 1) {
2553 status
= NT_STATUS_UNSUCCESSFUL
;
2557 /* extract the port from the answer */
2559 status
= dcerpc_binding_from_tower(tmp_ctx
,
2560 &(towers
.twr
->tower
),
2562 if (!NT_STATUS_IS_OK(status
)) {
2566 /* are further checks here necessary? */
2567 if (res_binding
->transport
!= NCACN_IP_TCP
) {
2568 status
= NT_STATUS_UNSUCCESSFUL
;
2572 *pport
= (uint16_t)atoi(res_binding
->endpoint
);
2575 TALLOC_FREE(tmp_ctx
);
2580 * Create a rpc pipe client struct, connecting to a host via tcp.
2581 * The port is determined by asking the endpoint mapper on the given
2584 NTSTATUS
rpc_pipe_open_tcp(TALLOC_CTX
*mem_ctx
, const char *host
,
2585 const struct ndr_syntax_id
*abstract_syntax
,
2586 struct rpc_pipe_client
**presult
)
2591 status
= rpc_pipe_get_tcp_port(host
, abstract_syntax
, &port
);
2592 if (!NT_STATUS_IS_OK(status
)) {
2596 return rpc_pipe_open_tcp_port(mem_ctx
, host
, port
,
2597 abstract_syntax
, presult
);
2600 /********************************************************************
2601 Create a rpc pipe client struct, connecting to a unix domain socket
2602 ********************************************************************/
2603 NTSTATUS
rpc_pipe_open_ncalrpc(TALLOC_CTX
*mem_ctx
, const char *socket_path
,
2604 const struct ndr_syntax_id
*abstract_syntax
,
2605 struct rpc_pipe_client
**presult
)
2607 struct rpc_pipe_client
*result
;
2608 struct sockaddr_un addr
;
2612 result
= talloc_zero(mem_ctx
, struct rpc_pipe_client
);
2613 if (result
== NULL
) {
2614 return NT_STATUS_NO_MEMORY
;
2617 result
->abstract_syntax
= *abstract_syntax
;
2618 result
->transfer_syntax
= ndr_transfer_syntax
;
2620 result
->desthost
= get_myname(result
);
2621 result
->srv_name_slash
= talloc_asprintf_strupper_m(
2622 result
, "\\\\%s", result
->desthost
);
2623 if ((result
->desthost
== NULL
) || (result
->srv_name_slash
== NULL
)) {
2624 status
= NT_STATUS_NO_MEMORY
;
2628 result
->max_xmit_frag
= RPC_MAX_PDU_FRAG_LEN
;
2629 result
->max_recv_frag
= RPC_MAX_PDU_FRAG_LEN
;
2631 fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
2633 status
= map_nt_error_from_unix(errno
);
2638 addr
.sun_family
= AF_UNIX
;
2639 strlcpy(addr
.sun_path
, socket_path
, sizeof(addr
.sun_path
));
2641 if (sys_connect(fd
, (struct sockaddr
*)(void *)&addr
) == -1) {
2642 DEBUG(0, ("connect(%s) failed: %s\n", socket_path
,
2645 return map_nt_error_from_unix(errno
);
2648 status
= rpc_transport_sock_init(result
, fd
, &result
->transport
);
2649 if (!NT_STATUS_IS_OK(status
)) {
2654 result
->transport
->transport
= NCALRPC
;
2656 result
->binding_handle
= rpccli_bh_create(result
);
2657 if (result
->binding_handle
== NULL
) {
2658 TALLOC_FREE(result
);
2659 return NT_STATUS_NO_MEMORY
;
2663 return NT_STATUS_OK
;
2666 TALLOC_FREE(result
);
2670 struct rpc_pipe_client_np_ref
{
2671 struct cli_state
*cli
;
2672 struct rpc_pipe_client
*pipe
;
2675 static int rpc_pipe_client_np_ref_destructor(struct rpc_pipe_client_np_ref
*np_ref
)
2677 DLIST_REMOVE(np_ref
->cli
->pipe_list
, np_ref
->pipe
);
2681 /****************************************************************************
2682 Open a named pipe over SMB to a remote server.
2684 * CAVEAT CALLER OF THIS FUNCTION:
2685 * The returned rpc_pipe_client saves a copy of the cli_state cli pointer,
2686 * so be sure that this function is called AFTER any structure (vs pointer)
2687 * assignment of the cli. In particular, libsmbclient does structure
2688 * assignments of cli, which invalidates the data in the returned
2689 * rpc_pipe_client if this function is called before the structure assignment
2692 ****************************************************************************/
2694 static NTSTATUS
rpc_pipe_open_np(struct cli_state
*cli
,
2695 const struct ndr_syntax_id
*abstract_syntax
,
2696 struct rpc_pipe_client
**presult
)
2698 struct rpc_pipe_client
*result
;
2700 struct rpc_pipe_client_np_ref
*np_ref
;
2702 /* sanity check to protect against crashes */
2705 return NT_STATUS_INVALID_HANDLE
;
2708 result
= talloc_zero(NULL
, struct rpc_pipe_client
);
2709 if (result
== NULL
) {
2710 return NT_STATUS_NO_MEMORY
;
2713 result
->abstract_syntax
= *abstract_syntax
;
2714 result
->transfer_syntax
= ndr_transfer_syntax
;
2715 result
->desthost
= talloc_strdup(result
, cli_state_remote_name(cli
));
2716 result
->srv_name_slash
= talloc_asprintf_strupper_m(
2717 result
, "\\\\%s", result
->desthost
);
2719 result
->max_xmit_frag
= RPC_MAX_PDU_FRAG_LEN
;
2720 result
->max_recv_frag
= RPC_MAX_PDU_FRAG_LEN
;
2722 if ((result
->desthost
== NULL
) || (result
->srv_name_slash
== NULL
)) {
2723 TALLOC_FREE(result
);
2724 return NT_STATUS_NO_MEMORY
;
2727 status
= rpc_transport_np_init(result
, cli
, abstract_syntax
,
2728 &result
->transport
);
2729 if (!NT_STATUS_IS_OK(status
)) {
2730 TALLOC_FREE(result
);
2734 result
->transport
->transport
= NCACN_NP
;
2736 np_ref
= talloc(result
->transport
, struct rpc_pipe_client_np_ref
);
2737 if (np_ref
== NULL
) {
2738 TALLOC_FREE(result
);
2739 return NT_STATUS_NO_MEMORY
;
2742 np_ref
->pipe
= result
;
2744 DLIST_ADD(np_ref
->cli
->pipe_list
, np_ref
->pipe
);
2745 talloc_set_destructor(np_ref
, rpc_pipe_client_np_ref_destructor
);
2747 result
->binding_handle
= rpccli_bh_create(result
);
2748 if (result
->binding_handle
== NULL
) {
2749 TALLOC_FREE(result
);
2750 return NT_STATUS_NO_MEMORY
;
2754 return NT_STATUS_OK
;
2757 /****************************************************************************
2758 Open a pipe to a remote server.
2759 ****************************************************************************/
2761 static NTSTATUS
cli_rpc_pipe_open(struct cli_state
*cli
,
2762 enum dcerpc_transport_t transport
,
2763 const struct ndr_syntax_id
*interface
,
2764 struct rpc_pipe_client
**presult
)
2766 switch (transport
) {
2768 return rpc_pipe_open_tcp(NULL
, cli_state_remote_name(cli
),
2769 interface
, presult
);
2771 return rpc_pipe_open_np(cli
, interface
, presult
);
2773 return NT_STATUS_NOT_IMPLEMENTED
;
2777 /****************************************************************************
2778 Open a named pipe to an SMB server and bind anonymously.
2779 ****************************************************************************/
2781 NTSTATUS
cli_rpc_pipe_open_noauth_transport(struct cli_state
*cli
,
2782 enum dcerpc_transport_t transport
,
2783 const struct ndr_syntax_id
*interface
,
2784 struct rpc_pipe_client
**presult
)
2786 struct rpc_pipe_client
*result
;
2787 struct pipe_auth_data
*auth
;
2790 status
= cli_rpc_pipe_open(cli
, transport
, interface
, &result
);
2791 if (!NT_STATUS_IS_OK(status
)) {
2795 status
= rpccli_anon_bind_data(result
, &auth
);
2796 if (!NT_STATUS_IS_OK(status
)) {
2797 DEBUG(0, ("rpccli_anon_bind_data returned %s\n",
2798 nt_errstr(status
)));
2799 TALLOC_FREE(result
);
2804 * This is a bit of an abstraction violation due to the fact that an
2805 * anonymous bind on an authenticated SMB inherits the user/domain
2806 * from the enclosing SMB creds
2809 TALLOC_FREE(auth
->user_name
);
2810 TALLOC_FREE(auth
->domain
);
2812 auth
->user_name
= talloc_strdup(auth
, cli
->user_name
);
2813 auth
->domain
= talloc_strdup(auth
, cli
->domain
);
2814 auth
->user_session_key
= data_blob_talloc(auth
,
2815 cli
->user_session_key
.data
,
2816 cli
->user_session_key
.length
);
2818 if ((auth
->user_name
== NULL
) || (auth
->domain
== NULL
)) {
2819 TALLOC_FREE(result
);
2820 return NT_STATUS_NO_MEMORY
;
2823 status
= rpc_pipe_bind(result
, auth
);
2824 if (!NT_STATUS_IS_OK(status
)) {
2826 if (ndr_syntax_id_equal(interface
,
2827 &ndr_table_dssetup
.syntax_id
)) {
2828 /* non AD domains just don't have this pipe, avoid
2829 * level 0 statement in that case - gd */
2832 DEBUG(lvl
, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
2833 "%s failed with error %s\n",
2834 get_pipe_name_from_syntax(talloc_tos(), interface
),
2835 nt_errstr(status
) ));
2836 TALLOC_FREE(result
);
2840 DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
2841 "%s and bound anonymously.\n",
2842 get_pipe_name_from_syntax(talloc_tos(), interface
),
2846 return NT_STATUS_OK
;
2849 /****************************************************************************
2850 ****************************************************************************/
2852 NTSTATUS
cli_rpc_pipe_open_noauth(struct cli_state
*cli
,
2853 const struct ndr_syntax_id
*interface
,
2854 struct rpc_pipe_client
**presult
)
2856 return cli_rpc_pipe_open_noauth_transport(cli
, NCACN_NP
,
2857 interface
, presult
);
2860 /****************************************************************************
2861 Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
2862 ****************************************************************************/
2864 NTSTATUS
cli_rpc_pipe_open_ntlmssp(struct cli_state
*cli
,
2865 const struct ndr_syntax_id
*interface
,
2866 enum dcerpc_transport_t transport
,
2867 enum dcerpc_AuthLevel auth_level
,
2869 const char *username
,
2870 const char *password
,
2871 struct rpc_pipe_client
**presult
)
2873 struct rpc_pipe_client
*result
;
2874 struct pipe_auth_data
*auth
= NULL
;
2875 enum dcerpc_AuthType auth_type
= DCERPC_AUTH_TYPE_NTLMSSP
;
2878 status
= cli_rpc_pipe_open(cli
, transport
, interface
, &result
);
2879 if (!NT_STATUS_IS_OK(status
)) {
2883 status
= rpccli_ntlmssp_bind_data(result
,
2884 auth_type
, auth_level
,
2885 domain
, username
, password
,
2887 if (!NT_STATUS_IS_OK(status
)) {
2888 DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
2889 nt_errstr(status
)));
2893 status
= rpc_pipe_bind(result
, auth
);
2894 if (!NT_STATUS_IS_OK(status
)) {
2895 DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
2896 nt_errstr(status
) ));
2900 DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
2901 "machine %s and bound NTLMSSP as user %s\\%s.\n",
2902 get_pipe_name_from_syntax(talloc_tos(), interface
),
2903 result
->desthost
, domain
, username
));
2906 return NT_STATUS_OK
;
2910 TALLOC_FREE(result
);
2914 /****************************************************************************
2916 Open a named pipe to an SMB server and bind using schannel (bind type 68)
2917 using session_key. sign and seal.
2919 The *pdc will be stolen onto this new pipe
2920 ****************************************************************************/
2922 NTSTATUS
cli_rpc_pipe_open_schannel_with_key(struct cli_state
*cli
,
2923 const struct ndr_syntax_id
*interface
,
2924 enum dcerpc_transport_t transport
,
2925 enum dcerpc_AuthLevel auth_level
,
2927 struct netlogon_creds_CredentialState
**pdc
,
2928 struct rpc_pipe_client
**presult
)
2930 struct rpc_pipe_client
*result
;
2931 struct pipe_auth_data
*auth
;
2934 status
= cli_rpc_pipe_open(cli
, transport
, interface
, &result
);
2935 if (!NT_STATUS_IS_OK(status
)) {
2939 status
= rpccli_schannel_bind_data(result
, domain
, auth_level
,
2941 if (!NT_STATUS_IS_OK(status
)) {
2942 DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
2943 nt_errstr(status
)));
2944 TALLOC_FREE(result
);
2948 status
= rpc_pipe_bind(result
, auth
);
2949 if (!NT_STATUS_IS_OK(status
)) {
2950 DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
2951 "cli_rpc_pipe_bind failed with error %s\n",
2952 nt_errstr(status
) ));
2953 TALLOC_FREE(result
);
2958 * The credentials on a new netlogon pipe are the ones we are passed
2959 * in - copy them over
2961 result
->dc
= netlogon_creds_copy(result
, *pdc
);
2962 if (result
->dc
== NULL
) {
2963 TALLOC_FREE(result
);
2964 return NT_STATUS_NO_MEMORY
;
2967 DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
2968 "for domain %s and bound using schannel.\n",
2969 get_pipe_name_from_syntax(talloc_tos(), interface
),
2970 result
->desthost
, domain
));
2973 return NT_STATUS_OK
;
2976 /****************************************************************************
2977 Open a named pipe to an SMB server and bind using krb5 (bind type 16).
2978 The idea is this can be called with service_princ, username and password all
2979 NULL so long as the caller has a TGT.
2980 ****************************************************************************/
2982 NTSTATUS
cli_rpc_pipe_open_krb5(struct cli_state
*cli
,
2983 const struct ndr_syntax_id
*interface
,
2984 enum dcerpc_transport_t transport
,
2985 enum dcerpc_AuthLevel auth_level
,
2987 const char *username
,
2988 const char *password
,
2989 struct rpc_pipe_client
**presult
)
2991 struct rpc_pipe_client
*result
;
2992 struct pipe_auth_data
*auth
;
2993 struct gse_context
*gse_ctx
;
2996 status
= cli_rpc_pipe_open(cli
, transport
, interface
, &result
);
2997 if (!NT_STATUS_IS_OK(status
)) {
3001 auth
= talloc(result
, struct pipe_auth_data
);
3003 status
= NT_STATUS_NO_MEMORY
;
3006 auth
->auth_type
= DCERPC_AUTH_TYPE_KRB5
;
3007 auth
->auth_level
= auth_level
;
3012 auth
->user_name
= talloc_strdup(auth
, username
);
3013 if (!auth
->user_name
) {
3014 status
= NT_STATUS_NO_MEMORY
;
3018 /* Fixme, should we fetch/set the Realm ? */
3019 auth
->domain
= talloc_strdup(auth
, "");
3020 if (!auth
->domain
) {
3021 status
= NT_STATUS_NO_MEMORY
;
3025 status
= gse_init_client(auth
,
3026 (auth_level
== DCERPC_AUTH_LEVEL_INTEGRITY
),
3027 (auth_level
== DCERPC_AUTH_LEVEL_PRIVACY
),
3028 NULL
, server
, "cifs", username
, password
,
3029 GSS_C_DCE_STYLE
, &gse_ctx
);
3030 if (!NT_STATUS_IS_OK(status
)) {
3031 DEBUG(0, ("gse_init_client returned %s\n",
3032 nt_errstr(status
)));
3035 auth
->auth_ctx
= gse_ctx
;
3037 status
= rpc_pipe_bind(result
, auth
);
3038 if (!NT_STATUS_IS_OK(status
)) {
3039 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3040 nt_errstr(status
)));
3045 return NT_STATUS_OK
;
3048 TALLOC_FREE(result
);
3052 NTSTATUS
cli_rpc_pipe_open_spnego_krb5(struct cli_state
*cli
,
3053 const struct ndr_syntax_id
*interface
,
3054 enum dcerpc_transport_t transport
,
3055 enum dcerpc_AuthLevel auth_level
,
3057 const char *username
,
3058 const char *password
,
3059 struct rpc_pipe_client
**presult
)
3061 struct rpc_pipe_client
*result
;
3062 struct pipe_auth_data
*auth
;
3063 struct spnego_context
*spnego_ctx
;
3066 status
= cli_rpc_pipe_open(cli
, transport
, interface
, &result
);
3067 if (!NT_STATUS_IS_OK(status
)) {
3071 auth
= talloc(result
, struct pipe_auth_data
);
3073 status
= NT_STATUS_NO_MEMORY
;
3076 auth
->auth_type
= DCERPC_AUTH_TYPE_SPNEGO
;
3077 auth
->auth_level
= auth_level
;
3082 auth
->user_name
= talloc_strdup(auth
, username
);
3083 if (!auth
->user_name
) {
3084 status
= NT_STATUS_NO_MEMORY
;
3088 /* Fixme, should we fetch/set the Realm ? */
3089 auth
->domain
= talloc_strdup(auth
, "");
3090 if (!auth
->domain
) {
3091 status
= NT_STATUS_NO_MEMORY
;
3095 status
= spnego_gssapi_init_client(auth
,
3096 (auth
->auth_level
==
3097 DCERPC_AUTH_LEVEL_INTEGRITY
),
3098 (auth
->auth_level
==
3099 DCERPC_AUTH_LEVEL_PRIVACY
),
3101 NULL
, server
, "cifs",
3104 if (!NT_STATUS_IS_OK(status
)) {
3105 DEBUG(0, ("spnego_init_client returned %s\n",
3106 nt_errstr(status
)));
3109 auth
->auth_ctx
= spnego_ctx
;
3111 status
= rpc_pipe_bind(result
, auth
);
3112 if (!NT_STATUS_IS_OK(status
)) {
3113 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3114 nt_errstr(status
)));
3119 return NT_STATUS_OK
;
3122 TALLOC_FREE(result
);
3126 NTSTATUS
cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state
*cli
,
3127 const struct ndr_syntax_id
*interface
,
3128 enum dcerpc_transport_t transport
,
3129 enum dcerpc_AuthLevel auth_level
,
3131 const char *username
,
3132 const char *password
,
3133 struct rpc_pipe_client
**presult
)
3135 struct rpc_pipe_client
*result
;
3136 struct pipe_auth_data
*auth
;
3137 struct spnego_context
*spnego_ctx
;
3140 status
= cli_rpc_pipe_open(cli
, transport
, interface
, &result
);
3141 if (!NT_STATUS_IS_OK(status
)) {
3145 auth
= talloc(result
, struct pipe_auth_data
);
3147 status
= NT_STATUS_NO_MEMORY
;
3150 auth
->auth_type
= DCERPC_AUTH_TYPE_SPNEGO
;
3151 auth
->auth_level
= auth_level
;
3156 auth
->user_name
= talloc_strdup(auth
, username
);
3157 if (!auth
->user_name
) {
3158 status
= NT_STATUS_NO_MEMORY
;
3165 auth
->domain
= talloc_strdup(auth
, domain
);
3166 if (!auth
->domain
) {
3167 status
= NT_STATUS_NO_MEMORY
;
3171 status
= spnego_ntlmssp_init_client(auth
,
3172 (auth
->auth_level
==
3173 DCERPC_AUTH_LEVEL_INTEGRITY
),
3174 (auth
->auth_level
==
3175 DCERPC_AUTH_LEVEL_PRIVACY
),
3177 domain
, username
, password
,
3179 if (!NT_STATUS_IS_OK(status
)) {
3180 DEBUG(0, ("spnego_init_client returned %s\n",
3181 nt_errstr(status
)));
3184 auth
->auth_ctx
= spnego_ctx
;
3186 status
= rpc_pipe_bind(result
, auth
);
3187 if (!NT_STATUS_IS_OK(status
)) {
3188 DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n",
3189 nt_errstr(status
)));
3194 return NT_STATUS_OK
;
3197 TALLOC_FREE(result
);
3201 NTSTATUS
cli_get_session_key(TALLOC_CTX
*mem_ctx
,
3202 struct rpc_pipe_client
*cli
,
3203 DATA_BLOB
*session_key
)
3206 struct pipe_auth_data
*a
;
3207 struct schannel_state
*schannel_auth
;
3208 struct gensec_security
*gensec_security
;
3209 struct spnego_context
*spnego_ctx
;
3210 struct gse_context
*gse_ctx
;
3211 DATA_BLOB sk
= data_blob_null
;
3212 bool make_dup
= false;
3214 if (!session_key
|| !cli
) {
3215 return NT_STATUS_INVALID_PARAMETER
;
3221 return NT_STATUS_INVALID_PARAMETER
;
3224 switch (cli
->auth
->auth_type
) {
3225 case DCERPC_AUTH_TYPE_SCHANNEL
:
3226 schannel_auth
= talloc_get_type_abort(a
->auth_ctx
,
3227 struct schannel_state
);
3228 sk
= data_blob_const(schannel_auth
->creds
->session_key
, 16);
3231 case DCERPC_AUTH_TYPE_SPNEGO
:
3232 spnego_ctx
= talloc_get_type_abort(a
->auth_ctx
,
3233 struct spnego_context
);
3234 sk
= spnego_get_session_key(mem_ctx
, spnego_ctx
);
3237 case DCERPC_AUTH_TYPE_NTLMSSP
:
3238 gensec_security
= talloc_get_type_abort(a
->auth_ctx
,
3239 struct gensec_security
);
3240 status
= gensec_session_key(gensec_security
, mem_ctx
, &sk
);
3241 if (!NT_STATUS_IS_OK(status
)) {
3246 case DCERPC_AUTH_TYPE_KRB5
:
3247 gse_ctx
= talloc_get_type_abort(a
->auth_ctx
,
3248 struct gse_context
);
3249 sk
= gse_get_session_key(mem_ctx
, gse_ctx
);
3252 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM
:
3253 case DCERPC_AUTH_TYPE_NONE
:
3254 sk
= data_blob_const(a
->user_session_key
.data
,
3255 a
->user_session_key
.length
);
3263 return NT_STATUS_NO_USER_SESSION_KEY
;
3267 *session_key
= data_blob_dup_talloc(mem_ctx
, sk
);
3272 return NT_STATUS_OK
;