2 Unix SMB/CIFS implementation.
5 Copyright (C) Tim Potter 2003
6 Copyright (C) Andrew Tridgell 2003-2005
7 Copyright (C) Jelmer Vernooij 2004-2005
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "../lib/util/dlinklist.h"
25 #include "lib/events/events.h"
26 #include "librpc/rpc/dcerpc.h"
27 #include "librpc/rpc/dcerpc_proto.h"
28 #include "librpc/gen_ndr/ndr_misc.h"
29 #include "librpc/gen_ndr/ndr_dcerpc.h"
30 #include "libcli/composite/composite.h"
31 #include "auth/gensec/gensec.h"
32 #include "param/param.h"
33 #include "lib/util/tevent_ntstatus.h"
34 #include "librpc/rpc/rpc_common.h"
36 enum rpc_request_state
{
43 handle for an async dcerpc request
46 struct rpc_request
*next
, *prev
;
47 struct dcerpc_pipe
*p
;
50 enum rpc_request_state state
;
55 /* this is used to distinguish bind and alter_context requests
56 from normal requests */
57 void (*recv_handler
)(struct rpc_request
*conn
,
58 DATA_BLOB
*blob
, struct ncacn_packet
*pkt
);
60 const struct GUID
*object
;
62 DATA_BLOB request_data
;
65 /* use by the ndr level async recv call */
67 const struct ndr_interface_table
*table
;
74 void (*callback
)(struct rpc_request
*);
79 _PUBLIC_ NTSTATUS
dcerpc_init(void)
84 static void dcerpc_connection_dead(struct dcecli_connection
*conn
, NTSTATUS status
);
85 static void dcerpc_ship_next_request(struct dcecli_connection
*c
);
87 static struct rpc_request
*dcerpc_request_send(struct dcerpc_pipe
*p
,
88 const struct GUID
*object
,
90 DATA_BLOB
*stub_data
);
91 static NTSTATUS
dcerpc_request_recv(struct rpc_request
*req
,
93 DATA_BLOB
*stub_data
);
94 static NTSTATUS
dcerpc_ndr_validate_in(struct dcecli_connection
*c
,
98 ndr_push_flags_fn_t ndr_push
,
99 ndr_pull_flags_fn_t ndr_pull
);
100 static NTSTATUS
dcerpc_ndr_validate_out(struct dcecli_connection
*c
,
101 struct ndr_pull
*pull_in
,
104 ndr_push_flags_fn_t ndr_push
,
105 ndr_pull_flags_fn_t ndr_pull
,
106 ndr_print_function_t ndr_print
);
108 /* destroy a dcerpc connection */
109 static int dcerpc_connection_destructor(struct dcecli_connection
*conn
)
112 conn
->free_skipped
= true;
115 dcerpc_connection_dead(conn
, NT_STATUS_LOCAL_DISCONNECT
);
120 /* initialise a dcerpc connection.
121 the event context is optional
123 static struct dcecli_connection
*dcerpc_connection_init(TALLOC_CTX
*mem_ctx
,
124 struct tevent_context
*ev
)
126 struct dcecli_connection
*c
;
128 c
= talloc_zero(mem_ctx
, struct dcecli_connection
);
135 if (c
->event_ctx
== NULL
) {
141 c
->security_state
.auth_info
= NULL
;
142 c
->security_state
.session_key
= dcerpc_generic_session_key
;
143 c
->security_state
.generic_state
= NULL
;
144 c
->binding_string
= NULL
;
146 c
->srv_max_xmit_frag
= 0;
147 c
->srv_max_recv_frag
= 0;
150 talloc_set_destructor(c
, dcerpc_connection_destructor
);
155 struct dcerpc_bh_state
{
156 struct dcerpc_pipe
*p
;
159 static bool dcerpc_bh_is_connected(struct dcerpc_binding_handle
*h
)
161 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
162 struct dcerpc_bh_state
);
171 static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle
*h
,
174 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
175 struct dcerpc_bh_state
);
179 return DCERPC_REQUEST_TIMEOUT
;
182 old
= hs
->p
->request_timeout
;
183 hs
->p
->request_timeout
= timeout
;
188 struct dcerpc_bh_raw_call_state
{
189 struct dcerpc_binding_handle
*h
;
195 static void dcerpc_bh_raw_call_done(struct rpc_request
*subreq
);
197 static struct tevent_req
*dcerpc_bh_raw_call_send(TALLOC_CTX
*mem_ctx
,
198 struct tevent_context
*ev
,
199 struct dcerpc_binding_handle
*h
,
200 const struct GUID
*object
,
203 const uint8_t *in_data
,
206 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
207 struct dcerpc_bh_state
);
208 struct tevent_req
*req
;
209 struct dcerpc_bh_raw_call_state
*state
;
211 struct rpc_request
*subreq
;
213 req
= tevent_req_create(mem_ctx
, &state
,
214 struct dcerpc_bh_raw_call_state
);
219 state
->in_data
.data
= discard_const_p(uint8_t, in_data
);
220 state
->in_data
.length
= in_length
;
222 ok
= dcerpc_bh_is_connected(h
);
224 tevent_req_nterror(req
, NT_STATUS_INVALID_CONNECTION
);
225 return tevent_req_post(req
, ev
);
228 subreq
= dcerpc_request_send(hs
->p
,
232 if (tevent_req_nomem(subreq
, req
)) {
233 return tevent_req_post(req
, ev
);
235 subreq
->async
.callback
= dcerpc_bh_raw_call_done
;
236 subreq
->async
.private_data
= req
;
241 static void dcerpc_bh_raw_call_done(struct rpc_request
*subreq
)
243 struct tevent_req
*req
=
244 talloc_get_type_abort(subreq
->async
.private_data
,
246 struct dcerpc_bh_raw_call_state
*state
=
248 struct dcerpc_bh_raw_call_state
);
252 state
->out_flags
= 0;
253 if (subreq
->flags
& DCERPC_PULL_BIGENDIAN
) {
254 state
->out_flags
|= LIBNDR_FLAG_BIGENDIAN
;
257 fault_code
= subreq
->fault_code
;
259 status
= dcerpc_request_recv(subreq
, state
, &state
->out_data
);
260 if (NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
261 status
= dcerpc_fault_to_nt_status(fault_code
);
263 if (!NT_STATUS_IS_OK(status
)) {
264 tevent_req_nterror(req
, status
);
268 tevent_req_done(req
);
271 static NTSTATUS
dcerpc_bh_raw_call_recv(struct tevent_req
*req
,
277 struct dcerpc_bh_raw_call_state
*state
=
279 struct dcerpc_bh_raw_call_state
);
282 if (tevent_req_is_nterror(req
, &status
)) {
283 tevent_req_received(req
);
287 *out_data
= talloc_move(mem_ctx
, &state
->out_data
.data
);
288 *out_length
= state
->out_data
.length
;
289 *out_flags
= state
->out_flags
;
290 tevent_req_received(req
);
294 struct dcerpc_bh_disconnect_state
{
298 static struct tevent_req
*dcerpc_bh_disconnect_send(TALLOC_CTX
*mem_ctx
,
299 struct tevent_context
*ev
,
300 struct dcerpc_binding_handle
*h
)
302 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
303 struct dcerpc_bh_state
);
304 struct tevent_req
*req
;
305 struct dcerpc_bh_disconnect_state
*state
;
308 req
= tevent_req_create(mem_ctx
, &state
,
309 struct dcerpc_bh_disconnect_state
);
314 ok
= dcerpc_bh_is_connected(h
);
316 tevent_req_nterror(req
, NT_STATUS_INVALID_CONNECTION
);
317 return tevent_req_post(req
, ev
);
320 /* TODO: do a real disconnect ... */
323 tevent_req_done(req
);
324 return tevent_req_post(req
, ev
);
327 static NTSTATUS
dcerpc_bh_disconnect_recv(struct tevent_req
*req
)
331 if (tevent_req_is_nterror(req
, &status
)) {
332 tevent_req_received(req
);
336 tevent_req_received(req
);
340 static bool dcerpc_bh_push_bigendian(struct dcerpc_binding_handle
*h
)
342 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
343 struct dcerpc_bh_state
);
345 if (hs
->p
->conn
->flags
& DCERPC_PUSH_BIGENDIAN
) {
352 static bool dcerpc_bh_ref_alloc(struct dcerpc_binding_handle
*h
)
354 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
355 struct dcerpc_bh_state
);
357 if (hs
->p
->conn
->flags
& DCERPC_NDR_REF_ALLOC
) {
364 static bool dcerpc_bh_use_ndr64(struct dcerpc_binding_handle
*h
)
366 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
367 struct dcerpc_bh_state
);
369 if (hs
->p
->conn
->flags
& DCERPC_NDR64
) {
376 static void dcerpc_bh_do_ndr_print(struct dcerpc_binding_handle
*h
,
378 const void *_struct_ptr
,
379 const struct ndr_interface_call
*call
)
381 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
382 struct dcerpc_bh_state
);
383 void *struct_ptr
= discard_const(_struct_ptr
);
385 if (ndr_flags
& NDR_IN
) {
386 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_PRINT_IN
) {
387 ndr_print_function_debug(call
->ndr_print
,
393 if (ndr_flags
& NDR_OUT
) {
394 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_PRINT_OUT
) {
395 ndr_print_function_debug(call
->ndr_print
,
403 static void dcerpc_bh_ndr_push_failed(struct dcerpc_binding_handle
*h
,
405 const void *struct_ptr
,
406 const struct ndr_interface_call
*call
)
408 DEBUG(2,("Unable to ndr_push structure for %s - %s\n",
409 call
->name
, nt_errstr(error
)));
412 static void dcerpc_bh_ndr_pull_failed(struct dcerpc_binding_handle
*h
,
414 const DATA_BLOB
*blob
,
415 const struct ndr_interface_call
*call
)
417 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
418 struct dcerpc_bh_state
);
419 const uint32_t num_examples
= 20;
422 DEBUG(2,("Unable to ndr_pull structure for %s - %s\n",
423 call
->name
, nt_errstr(error
)));
425 if (hs
->p
->conn
->packet_log_dir
== NULL
) return;
427 for (i
=0;i
<num_examples
;i
++) {
429 asprintf(&name
, "%s/rpclog/%s-out.%d",
430 hs
->p
->conn
->packet_log_dir
,
435 if (!file_exist(name
)) {
436 if (file_save(name
, blob
->data
, blob
->length
)) {
437 DEBUG(10,("Logged rpc packet to %s\n", name
));
446 static NTSTATUS
dcerpc_bh_ndr_validate_in(struct dcerpc_binding_handle
*h
,
448 const DATA_BLOB
*blob
,
449 const struct ndr_interface_call
*call
)
451 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
452 struct dcerpc_bh_state
);
454 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_VALIDATE_IN
) {
457 status
= dcerpc_ndr_validate_in(hs
->p
->conn
,
463 if (!NT_STATUS_IS_OK(status
)) {
464 DEBUG(0,("Validation [in] failed for %s - %s\n",
465 call
->name
, nt_errstr(status
)));
470 DEBUG(10,("rpc request data:\n"));
471 dump_data(10, blob
->data
, blob
->length
);
476 static NTSTATUS
dcerpc_bh_ndr_validate_out(struct dcerpc_binding_handle
*h
,
477 struct ndr_pull
*pull_in
,
478 const void *_struct_ptr
,
479 const struct ndr_interface_call
*call
)
481 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
482 struct dcerpc_bh_state
);
483 void *struct_ptr
= discard_const(_struct_ptr
);
485 DEBUG(10,("rpc reply data:\n"));
486 dump_data(10, pull_in
->data
, pull_in
->data_size
);
488 if (pull_in
->offset
!= pull_in
->data_size
) {
489 DEBUG(0,("Warning! ignoring %u unread bytes at ofs:%u (0x%08X) for %s!\n",
490 pull_in
->data_size
- pull_in
->offset
,
491 pull_in
->offset
, pull_in
->offset
,
493 /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here,
494 but it turns out that early versions of NT
495 (specifically NT3.1) add junk onto the end of rpc
496 packets, so if we want to interoperate at all with
497 those versions then we need to ignore this error */
500 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_VALIDATE_OUT
) {
503 status
= dcerpc_ndr_validate_out(hs
->p
->conn
,
510 if (!NT_STATUS_IS_OK(status
)) {
511 DEBUG(2,("Validation [out] failed for %s - %s\n",
512 call
->name
, nt_errstr(status
)));
520 static const struct dcerpc_binding_handle_ops dcerpc_bh_ops
= {
522 .is_connected
= dcerpc_bh_is_connected
,
523 .set_timeout
= dcerpc_bh_set_timeout
,
524 .raw_call_send
= dcerpc_bh_raw_call_send
,
525 .raw_call_recv
= dcerpc_bh_raw_call_recv
,
526 .disconnect_send
= dcerpc_bh_disconnect_send
,
527 .disconnect_recv
= dcerpc_bh_disconnect_recv
,
529 .push_bigendian
= dcerpc_bh_push_bigendian
,
530 .ref_alloc
= dcerpc_bh_ref_alloc
,
531 .use_ndr64
= dcerpc_bh_use_ndr64
,
532 .do_ndr_print
= dcerpc_bh_do_ndr_print
,
533 .ndr_push_failed
= dcerpc_bh_ndr_push_failed
,
534 .ndr_pull_failed
= dcerpc_bh_ndr_pull_failed
,
535 .ndr_validate_in
= dcerpc_bh_ndr_validate_in
,
536 .ndr_validate_out
= dcerpc_bh_ndr_validate_out
,
539 /* initialise a dcerpc pipe. */
540 struct dcerpc_binding_handle
*dcerpc_pipe_binding_handle(struct dcerpc_pipe
*p
)
542 struct dcerpc_binding_handle
*h
;
543 struct dcerpc_bh_state
*hs
;
545 h
= dcerpc_binding_handle_create(p
,
550 struct dcerpc_bh_state
,
557 dcerpc_binding_handle_set_sync_ev(h
, p
->conn
->event_ctx
);
562 /* initialise a dcerpc pipe. */
563 _PUBLIC_
struct dcerpc_pipe
*dcerpc_pipe_init(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
)
565 struct dcerpc_pipe
*p
;
567 p
= talloc_zero(mem_ctx
, struct dcerpc_pipe
);
572 p
->conn
= dcerpc_connection_init(p
, ev
);
573 if (p
->conn
== NULL
) {
578 p
->last_fault_code
= 0;
580 p
->request_timeout
= DCERPC_REQUEST_TIMEOUT
;
583 ZERO_STRUCT(p
->syntax
);
584 ZERO_STRUCT(p
->transfer_syntax
);
587 p
->conn
->flags
|= DCERPC_DEBUG_PRINT_BOTH
;
590 p
->binding_handle
= dcerpc_pipe_binding_handle(p
);
591 if (p
->binding_handle
== NULL
) {
601 choose the next call id to use
603 static uint32_t next_call_id(struct dcecli_connection
*c
)
606 if (c
->call_id
== 0) {
613 setup for a ndr pull, also setting up any flags from the binding string
615 static struct ndr_pull
*ndr_pull_init_flags(struct dcecli_connection
*c
,
616 DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
)
618 struct ndr_pull
*ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
620 if (ndr
== NULL
) return ndr
;
622 if (c
->flags
& DCERPC_DEBUG_PAD_CHECK
) {
623 ndr
->flags
|= LIBNDR_FLAG_PAD_CHECK
;
626 if (c
->flags
& DCERPC_NDR_REF_ALLOC
) {
627 ndr
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
630 if (c
->flags
& DCERPC_NDR64
) {
631 ndr
->flags
|= LIBNDR_FLAG_NDR64
;
638 parse a data blob into a ncacn_packet structure. This handles both
639 input and output packets
641 static NTSTATUS
ncacn_pull(struct dcecli_connection
*c
, DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
642 struct ncacn_packet
*pkt
)
644 struct ndr_pull
*ndr
;
645 enum ndr_err_code ndr_err
;
647 ndr
= ndr_pull_init_flags(c
, blob
, mem_ctx
);
649 return NT_STATUS_NO_MEMORY
;
652 if (! (CVAL(blob
->data
, DCERPC_DREP_OFFSET
) & DCERPC_DREP_LE
)) {
653 ndr
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
656 ndr_err
= ndr_pull_ncacn_packet(ndr
, NDR_SCALARS
|NDR_BUFFERS
, pkt
);
657 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
658 return ndr_map_error2ntstatus(ndr_err
);
665 parse the authentication information on a dcerpc response packet
667 static NTSTATUS
ncacn_pull_request_auth(struct dcecli_connection
*c
, TALLOC_CTX
*mem_ctx
,
668 DATA_BLOB
*raw_packet
,
669 struct ncacn_packet
*pkt
)
672 struct dcerpc_auth auth
;
673 uint32_t auth_length
;
675 if (!c
->security_state
.auth_info
||
676 !c
->security_state
.generic_state
) {
680 switch (c
->security_state
.auth_info
->auth_level
) {
681 case DCERPC_AUTH_LEVEL_PRIVACY
:
682 case DCERPC_AUTH_LEVEL_INTEGRITY
:
685 case DCERPC_AUTH_LEVEL_CONNECT
:
686 if (pkt
->auth_length
!= 0) {
690 case DCERPC_AUTH_LEVEL_NONE
:
691 if (pkt
->auth_length
!= 0) {
692 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
697 return NT_STATUS_INVALID_LEVEL
;
700 status
= dcerpc_pull_auth_trailer(pkt
, mem_ctx
,
701 &pkt
->u
.response
.stub_and_verifier
,
702 &auth
, &auth_length
, false);
703 NT_STATUS_NOT_OK_RETURN(status
);
705 pkt
->u
.response
.stub_and_verifier
.length
-= auth_length
;
707 /* check signature or unseal the packet */
708 switch (c
->security_state
.auth_info
->auth_level
) {
709 case DCERPC_AUTH_LEVEL_PRIVACY
:
710 status
= gensec_unseal_packet(c
->security_state
.generic_state
,
712 raw_packet
->data
+ DCERPC_REQUEST_LENGTH
,
713 pkt
->u
.response
.stub_and_verifier
.length
,
715 raw_packet
->length
- auth
.credentials
.length
,
717 memcpy(pkt
->u
.response
.stub_and_verifier
.data
,
718 raw_packet
->data
+ DCERPC_REQUEST_LENGTH
,
719 pkt
->u
.response
.stub_and_verifier
.length
);
722 case DCERPC_AUTH_LEVEL_INTEGRITY
:
723 status
= gensec_check_packet(c
->security_state
.generic_state
,
725 pkt
->u
.response
.stub_and_verifier
.data
,
726 pkt
->u
.response
.stub_and_verifier
.length
,
728 raw_packet
->length
- auth
.credentials
.length
,
732 case DCERPC_AUTH_LEVEL_CONNECT
:
733 /* for now we ignore possible signatures here */
734 status
= NT_STATUS_OK
;
738 status
= NT_STATUS_INVALID_LEVEL
;
742 /* remove the indicated amount of padding */
743 if (pkt
->u
.response
.stub_and_verifier
.length
< auth
.auth_pad_length
) {
744 return NT_STATUS_INFO_LENGTH_MISMATCH
;
746 pkt
->u
.response
.stub_and_verifier
.length
-= auth
.auth_pad_length
;
753 push a dcerpc request packet into a blob, possibly signing it.
755 static NTSTATUS
ncacn_push_request_sign(struct dcecli_connection
*c
,
756 DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
758 struct ncacn_packet
*pkt
)
761 struct ndr_push
*ndr
;
763 size_t payload_length
;
764 enum ndr_err_code ndr_err
;
765 size_t hdr_size
= DCERPC_REQUEST_LENGTH
;
767 /* non-signed packets are simpler */
769 return ncacn_push_auth(blob
, mem_ctx
, pkt
, NULL
);
772 switch (c
->security_state
.auth_info
->auth_level
) {
773 case DCERPC_AUTH_LEVEL_PRIVACY
:
774 case DCERPC_AUTH_LEVEL_INTEGRITY
:
777 case DCERPC_AUTH_LEVEL_CONNECT
:
778 /* TODO: let the gensec mech decide if it wants to generate a signature */
779 return ncacn_push_auth(blob
, mem_ctx
, pkt
, NULL
);
781 case DCERPC_AUTH_LEVEL_NONE
:
782 return ncacn_push_auth(blob
, mem_ctx
, pkt
, NULL
);
785 return NT_STATUS_INVALID_LEVEL
;
788 ndr
= ndr_push_init_ctx(mem_ctx
);
790 return NT_STATUS_NO_MEMORY
;
793 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
794 ndr
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
797 if (c
->flags
& DCERPC_NDR64
) {
798 ndr
->flags
|= LIBNDR_FLAG_NDR64
;
801 if (pkt
->pfc_flags
& DCERPC_PFC_FLAG_OBJECT_UUID
) {
802 ndr
->flags
|= LIBNDR_FLAG_OBJECT_PRESENT
;
806 ndr_err
= ndr_push_ncacn_packet(ndr
, NDR_SCALARS
|NDR_BUFFERS
, pkt
);
807 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
808 return ndr_map_error2ntstatus(ndr_err
);
811 /* pad to 16 byte multiple in the payload portion of the
812 packet. This matches what w2k3 does. Note that we can't use
813 ndr_push_align() as that is relative to the start of the
814 whole packet, whereas w2k8 wants it relative to the start
816 c
->security_state
.auth_info
->auth_pad_length
=
817 (16 - (pkt
->u
.request
.stub_and_verifier
.length
& 15)) & 15;
818 ndr_err
= ndr_push_zero(ndr
, c
->security_state
.auth_info
->auth_pad_length
);
819 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
820 return ndr_map_error2ntstatus(ndr_err
);
823 payload_length
= pkt
->u
.request
.stub_and_verifier
.length
+
824 c
->security_state
.auth_info
->auth_pad_length
;
826 /* we start without signature, it will appended later */
827 c
->security_state
.auth_info
->credentials
= data_blob(NULL
,0);
829 /* add the auth verifier */
830 ndr_err
= ndr_push_dcerpc_auth(ndr
, NDR_SCALARS
|NDR_BUFFERS
, c
->security_state
.auth_info
);
831 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
832 return ndr_map_error2ntstatus(ndr_err
);
835 /* extract the whole packet as a blob */
836 *blob
= ndr_push_blob(ndr
);
839 * Setup the frag and auth length in the packet buffer.
840 * This is needed if the GENSEC mech does AEAD signing
841 * of the packet headers. The signature itself will be
844 dcerpc_set_frag_length(blob
, blob
->length
+ sig_size
);
845 dcerpc_set_auth_length(blob
, sig_size
);
847 /* sign or seal the packet */
848 switch (c
->security_state
.auth_info
->auth_level
) {
849 case DCERPC_AUTH_LEVEL_PRIVACY
:
850 status
= gensec_seal_packet(c
->security_state
.generic_state
,
852 blob
->data
+ hdr_size
,
857 if (!NT_STATUS_IS_OK(status
)) {
862 case DCERPC_AUTH_LEVEL_INTEGRITY
:
863 status
= gensec_sign_packet(c
->security_state
.generic_state
,
865 blob
->data
+ hdr_size
,
870 if (!NT_STATUS_IS_OK(status
)) {
876 status
= NT_STATUS_INVALID_LEVEL
;
880 if (creds2
.length
!= sig_size
) {
881 /* this means the sig_size estimate for the signature
882 was incorrect. We have to correct the packet
883 sizes. That means we could go over the max fragment
885 DEBUG(3,("ncacn_push_request_sign: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n",
886 (unsigned) creds2
.length
,
888 (unsigned) c
->security_state
.auth_info
->auth_pad_length
,
889 (unsigned) pkt
->u
.request
.stub_and_verifier
.length
));
890 dcerpc_set_frag_length(blob
, blob
->length
+ creds2
.length
);
891 dcerpc_set_auth_length(blob
, creds2
.length
);
894 if (!data_blob_append(mem_ctx
, blob
, creds2
.data
, creds2
.length
)) {
895 return NT_STATUS_NO_MEMORY
;
903 fill in the fixed values in a dcerpc header
905 static void init_ncacn_hdr(struct dcecli_connection
*c
, struct ncacn_packet
*pkt
)
908 pkt
->rpc_vers_minor
= 0;
909 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
912 pkt
->drep
[0] = DCERPC_DREP_LE
;
920 map a bind nak reason to a NTSTATUS
922 static NTSTATUS
dcerpc_map_reason(uint16_t reason
)
925 case DCERPC_BIND_REASON_ASYNTAX
:
926 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX
;
927 case DCERPC_BIND_REASON_INVALID_AUTH_TYPE
:
928 return NT_STATUS_INVALID_PARAMETER
;
930 return NT_STATUS_UNSUCCESSFUL
;
934 a bind or alter context has failed
936 static void dcerpc_composite_fail(struct rpc_request
*req
)
938 struct composite_context
*c
= talloc_get_type(req
->async
.private_data
,
939 struct composite_context
);
940 composite_error(c
, req
->status
);
944 remove requests from the pending or queued queues
946 static int dcerpc_req_dequeue(struct rpc_request
*req
)
948 switch (req
->state
) {
949 case RPC_REQUEST_QUEUED
:
950 DLIST_REMOVE(req
->p
->conn
->request_queue
, req
);
952 case RPC_REQUEST_PENDING
:
953 DLIST_REMOVE(req
->p
->conn
->pending
, req
);
955 case RPC_REQUEST_DONE
:
963 mark the dcerpc connection dead. All outstanding requests get an error
965 static void dcerpc_connection_dead(struct dcecli_connection
*conn
, NTSTATUS status
)
967 if (conn
->dead
) return;
971 if (conn
->transport
.shutdown_pipe
) {
972 conn
->transport
.shutdown_pipe(conn
, status
);
975 /* all pending requests get the error */
976 while (conn
->pending
) {
977 struct rpc_request
*req
= conn
->pending
;
978 dcerpc_req_dequeue(req
);
979 req
->state
= RPC_REQUEST_DONE
;
980 req
->status
= status
;
981 if (req
->async
.callback
) {
982 req
->async
.callback(req
);
986 talloc_set_destructor(conn
, NULL
);
987 if (conn
->free_skipped
) {
993 forward declarations of the recv_data handlers for the types of
994 packets we need to handle
996 static void dcerpc_request_recv_data(struct dcecli_connection
*c
,
997 DATA_BLOB
*raw_packet
, struct ncacn_packet
*pkt
);
1000 receive a dcerpc reply from the transport. Here we work out what
1001 type of reply it is (normal request, bind or alter context) and
1002 dispatch to the appropriate handler
1004 static void dcerpc_recv_data(struct dcecli_connection
*conn
, DATA_BLOB
*blob
, NTSTATUS status
)
1006 struct ncacn_packet pkt
;
1008 if (NT_STATUS_IS_OK(status
) && blob
->length
== 0) {
1009 status
= NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
1012 /* the transport may be telling us of a severe error, such as
1014 if (!NT_STATUS_IS_OK(status
)) {
1015 data_blob_free(blob
);
1016 dcerpc_connection_dead(conn
, status
);
1020 /* parse the basic packet to work out what type of response this is */
1021 status
= ncacn_pull(conn
, blob
, blob
->data
, &pkt
);
1022 if (!NT_STATUS_IS_OK(status
)) {
1023 data_blob_free(blob
);
1024 dcerpc_connection_dead(conn
, status
);
1027 dcerpc_request_recv_data(conn
, blob
, &pkt
);
1031 Receive a bind reply from the transport
1033 static void dcerpc_bind_recv_handler(struct rpc_request
*req
,
1034 DATA_BLOB
*raw_packet
, struct ncacn_packet
*pkt
)
1036 struct composite_context
*c
;
1037 struct dcecli_connection
*conn
;
1039 c
= talloc_get_type(req
->async
.private_data
, struct composite_context
);
1041 if (pkt
->ptype
== DCERPC_PKT_BIND_NAK
) {
1042 DEBUG(2,("dcerpc: bind_nak reason %d\n",
1043 pkt
->u
.bind_nak
.reject_reason
));
1044 composite_error(c
, dcerpc_map_reason(pkt
->u
.bind_nak
.
1049 if ((pkt
->ptype
!= DCERPC_PKT_BIND_ACK
) ||
1050 (pkt
->u
.bind_ack
.num_results
== 0) ||
1051 (pkt
->u
.bind_ack
.ctx_list
[0].result
!= 0)) {
1052 req
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
1053 composite_error(c
, NT_STATUS_NET_WRITE_FAULT
);
1057 conn
= req
->p
->conn
;
1059 conn
->srv_max_xmit_frag
= pkt
->u
.bind_ack
.max_xmit_frag
;
1060 conn
->srv_max_recv_frag
= pkt
->u
.bind_ack
.max_recv_frag
;
1062 if ((req
->p
->binding
->flags
& DCERPC_CONCURRENT_MULTIPLEX
) &&
1063 (pkt
->pfc_flags
& DCERPC_PFC_FLAG_CONC_MPX
)) {
1064 conn
->flags
|= DCERPC_CONCURRENT_MULTIPLEX
;
1067 if ((req
->p
->binding
->flags
& DCERPC_HEADER_SIGNING
) &&
1068 (pkt
->pfc_flags
& DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
)) {
1069 conn
->flags
|= DCERPC_HEADER_SIGNING
;
1072 /* the bind_ack might contain a reply set of credentials */
1073 if (conn
->security_state
.auth_info
&& pkt
->u
.bind_ack
.auth_info
.length
) {
1075 uint32_t auth_length
;
1076 status
= dcerpc_pull_auth_trailer(pkt
, conn
, &pkt
->u
.bind_ack
.auth_info
,
1077 conn
->security_state
.auth_info
, &auth_length
, true);
1078 if (!NT_STATUS_IS_OK(status
)) {
1079 composite_error(c
, status
);
1084 req
->p
->assoc_group_id
= pkt
->u
.bind_ack
.assoc_group_id
;
1090 handle timeouts of individual dcerpc requests
1092 static void dcerpc_timeout_handler(struct tevent_context
*ev
, struct tevent_timer
*te
,
1093 struct timeval t
, void *private_data
)
1095 struct rpc_request
*req
= talloc_get_type(private_data
, struct rpc_request
);
1097 if (req
->ignore_timeout
) {
1098 dcerpc_req_dequeue(req
);
1099 req
->state
= RPC_REQUEST_DONE
;
1100 req
->status
= NT_STATUS_IO_TIMEOUT
;
1101 if (req
->async
.callback
) {
1102 req
->async
.callback(req
);
1107 dcerpc_connection_dead(req
->p
->conn
, NT_STATUS_IO_TIMEOUT
);
1111 send a async dcerpc bind request
1113 struct composite_context
*dcerpc_bind_send(struct dcerpc_pipe
*p
,
1114 TALLOC_CTX
*mem_ctx
,
1115 const struct ndr_syntax_id
*syntax
,
1116 const struct ndr_syntax_id
*transfer_syntax
)
1118 struct composite_context
*c
;
1119 struct ncacn_packet pkt
;
1121 struct rpc_request
*req
;
1123 c
= composite_create(mem_ctx
,p
->conn
->event_ctx
);
1124 if (c
== NULL
) return NULL
;
1126 c
->private_data
= p
;
1128 p
->syntax
= *syntax
;
1129 p
->transfer_syntax
= *transfer_syntax
;
1131 init_ncacn_hdr(p
->conn
, &pkt
);
1133 pkt
.ptype
= DCERPC_PKT_BIND
;
1134 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
1135 pkt
.call_id
= p
->conn
->call_id
;
1136 pkt
.auth_length
= 0;
1138 if (p
->binding
->flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
1139 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
1142 if (p
->binding
->flags
& DCERPC_HEADER_SIGNING
) {
1143 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
;
1146 pkt
.u
.bind
.max_xmit_frag
= 5840;
1147 pkt
.u
.bind
.max_recv_frag
= 5840;
1148 pkt
.u
.bind
.assoc_group_id
= p
->binding
->assoc_group_id
;
1149 pkt
.u
.bind
.num_contexts
= 1;
1150 pkt
.u
.bind
.ctx_list
= talloc_array(mem_ctx
, struct dcerpc_ctx_list
, 1);
1151 if (composite_nomem(pkt
.u
.bind
.ctx_list
, c
)) return c
;
1152 pkt
.u
.bind
.ctx_list
[0].context_id
= p
->context_id
;
1153 pkt
.u
.bind
.ctx_list
[0].num_transfer_syntaxes
= 1;
1154 pkt
.u
.bind
.ctx_list
[0].abstract_syntax
= p
->syntax
;
1155 pkt
.u
.bind
.ctx_list
[0].transfer_syntaxes
= &p
->transfer_syntax
;
1156 pkt
.u
.bind
.auth_info
= data_blob(NULL
, 0);
1158 /* construct the NDR form of the packet */
1159 c
->status
= ncacn_push_auth(&blob
, c
, &pkt
,
1160 p
->conn
->security_state
.auth_info
);
1161 if (!composite_is_ok(c
)) return c
;
1163 p
->conn
->transport
.recv_data
= dcerpc_recv_data
;
1166 * we allocate a dcerpc_request so we can be in the same
1167 * request queue as normal requests
1169 req
= talloc_zero(c
, struct rpc_request
);
1170 if (composite_nomem(req
, c
)) return c
;
1172 req
->state
= RPC_REQUEST_PENDING
;
1173 req
->call_id
= pkt
.call_id
;
1174 req
->async
.private_data
= c
;
1175 req
->async
.callback
= dcerpc_composite_fail
;
1177 req
->recv_handler
= dcerpc_bind_recv_handler
;
1178 DLIST_ADD_END(p
->conn
->pending
, req
, struct rpc_request
*);
1179 talloc_set_destructor(req
, dcerpc_req_dequeue
);
1181 c
->status
= p
->conn
->transport
.send_request(p
->conn
, &blob
,
1183 if (!composite_is_ok(c
)) return c
;
1185 event_add_timed(c
->event_ctx
, req
,
1186 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT
, 0),
1187 dcerpc_timeout_handler
, req
);
1193 recv side of async dcerpc bind request
1195 NTSTATUS
dcerpc_bind_recv(struct composite_context
*ctx
)
1197 NTSTATUS result
= composite_wait(ctx
);
1203 perform a continued bind (and auth3)
1205 NTSTATUS
dcerpc_auth3(struct dcerpc_pipe
*p
,
1206 TALLOC_CTX
*mem_ctx
)
1208 struct ncacn_packet pkt
;
1212 init_ncacn_hdr(p
->conn
, &pkt
);
1214 pkt
.ptype
= DCERPC_PKT_AUTH3
;
1215 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
1216 pkt
.call_id
= next_call_id(p
->conn
);
1217 pkt
.auth_length
= 0;
1218 pkt
.u
.auth3
.auth_info
= data_blob(NULL
, 0);
1220 if (p
->binding
->flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
1221 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
1224 if (p
->binding
->flags
& DCERPC_HEADER_SIGNING
) {
1225 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
;
1228 /* construct the NDR form of the packet */
1229 status
= ncacn_push_auth(&blob
, mem_ctx
,
1231 p
->conn
->security_state
.auth_info
);
1232 if (!NT_STATUS_IS_OK(status
)) {
1236 /* send it on its way */
1237 status
= p
->conn
->transport
.send_request(p
->conn
, &blob
, false);
1238 if (!NT_STATUS_IS_OK(status
)) {
1242 return NT_STATUS_OK
;
1247 process a fragment received from the transport layer during a
1250 This function frees the data
1252 static void dcerpc_request_recv_data(struct dcecli_connection
*c
,
1253 DATA_BLOB
*raw_packet
, struct ncacn_packet
*pkt
)
1255 struct rpc_request
*req
;
1256 unsigned int length
;
1257 NTSTATUS status
= NT_STATUS_OK
;
1260 if this is an authenticated connection then parse and check
1261 the auth info. We have to do this before finding the
1262 matching packet, as the request structure might have been
1263 removed due to a timeout, but if it has been we still need
1264 to run the auth routines so that we don't get the sign/seal
1265 info out of step with the server
1267 if (c
->security_state
.auth_info
&& c
->security_state
.generic_state
&&
1268 pkt
->ptype
== DCERPC_PKT_RESPONSE
) {
1269 status
= ncacn_pull_request_auth(c
, raw_packet
->data
, raw_packet
, pkt
);
1272 /* find the matching request */
1273 for (req
=c
->pending
;req
;req
=req
->next
) {
1274 if (pkt
->call_id
== req
->call_id
) break;
1278 /* useful for testing certain vendors RPC servers */
1279 if (req
== NULL
&& c
->pending
&& pkt
->call_id
== 0) {
1280 DEBUG(0,("HACK FOR INCORRECT CALL ID\n"));
1286 DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt
->call_id
));
1287 data_blob_free(raw_packet
);
1291 talloc_steal(req
, raw_packet
->data
);
1293 if (req
->recv_handler
!= NULL
) {
1294 dcerpc_req_dequeue(req
);
1295 req
->state
= RPC_REQUEST_DONE
;
1296 req
->recv_handler(req
, raw_packet
, pkt
);
1300 if (pkt
->ptype
== DCERPC_PKT_FAULT
) {
1301 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c
, pkt
->u
.fault
.status
)));
1302 req
->fault_code
= pkt
->u
.fault
.status
;
1303 req
->status
= NT_STATUS_NET_WRITE_FAULT
;
1307 if (pkt
->ptype
!= DCERPC_PKT_RESPONSE
) {
1308 DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
1310 req
->fault_code
= DCERPC_FAULT_OTHER
;
1311 req
->status
= NT_STATUS_NET_WRITE_FAULT
;
1315 /* now check the status from the auth routines, and if it failed then fail
1316 this request accordingly */
1317 if (!NT_STATUS_IS_OK(status
)) {
1318 req
->status
= status
;
1322 length
= pkt
->u
.response
.stub_and_verifier
.length
;
1325 req
->payload
.data
= talloc_realloc(req
,
1328 req
->payload
.length
+ length
);
1329 if (!req
->payload
.data
) {
1330 req
->status
= NT_STATUS_NO_MEMORY
;
1333 memcpy(req
->payload
.data
+req
->payload
.length
,
1334 pkt
->u
.response
.stub_and_verifier
.data
, length
);
1335 req
->payload
.length
+= length
;
1338 if (!(pkt
->pfc_flags
& DCERPC_PFC_FLAG_LAST
)) {
1339 c
->transport
.send_read(c
);
1343 if (!(pkt
->drep
[0] & DCERPC_DREP_LE
)) {
1344 req
->flags
|= DCERPC_PULL_BIGENDIAN
;
1346 req
->flags
&= ~DCERPC_PULL_BIGENDIAN
;
1351 /* we've got the full payload */
1352 req
->state
= RPC_REQUEST_DONE
;
1353 DLIST_REMOVE(c
->pending
, req
);
1355 if (c
->request_queue
!= NULL
) {
1356 /* We have to look at shipping further requests before calling
1357 * the async function, that one might close the pipe */
1358 dcerpc_ship_next_request(c
);
1361 if (req
->async
.callback
) {
1362 req
->async
.callback(req
);
1367 perform the send side of a async dcerpc request
1369 static struct rpc_request
*dcerpc_request_send(struct dcerpc_pipe
*p
,
1370 const struct GUID
*object
,
1372 DATA_BLOB
*stub_data
)
1374 struct rpc_request
*req
;
1376 p
->conn
->transport
.recv_data
= dcerpc_recv_data
;
1378 req
= talloc(p
, struct rpc_request
);
1384 req
->call_id
= next_call_id(p
->conn
);
1385 req
->status
= NT_STATUS_OK
;
1386 req
->state
= RPC_REQUEST_QUEUED
;
1387 req
->payload
= data_blob(NULL
, 0);
1389 req
->fault_code
= 0;
1390 req
->ignore_timeout
= false;
1391 req
->async
.callback
= NULL
;
1392 req
->async
.private_data
= NULL
;
1393 req
->recv_handler
= NULL
;
1395 if (object
!= NULL
) {
1396 req
->object
= (struct GUID
*)talloc_memdup(req
, (const void *)object
, sizeof(*object
));
1397 if (req
->object
== NULL
) {
1406 req
->request_data
.length
= stub_data
->length
;
1407 req
->request_data
.data
= talloc_reference(req
, stub_data
->data
);
1408 if (req
->request_data
.length
&& req
->request_data
.data
== NULL
) {
1412 DLIST_ADD_END(p
->conn
->request_queue
, req
, struct rpc_request
*);
1413 talloc_set_destructor(req
, dcerpc_req_dequeue
);
1415 dcerpc_ship_next_request(p
->conn
);
1417 if (p
->request_timeout
) {
1418 event_add_timed(dcerpc_event_context(p
), req
,
1419 timeval_current_ofs(p
->request_timeout
, 0),
1420 dcerpc_timeout_handler
, req
);
1427 Send a request using the transport
1430 static void dcerpc_ship_next_request(struct dcecli_connection
*c
)
1432 struct rpc_request
*req
;
1433 struct dcerpc_pipe
*p
;
1434 DATA_BLOB
*stub_data
;
1435 struct ncacn_packet pkt
;
1437 uint32_t remaining
, chunk_size
;
1438 bool first_packet
= true;
1439 size_t sig_size
= 0;
1440 bool need_async
= false;
1442 req
= c
->request_queue
;
1448 stub_data
= &req
->request_data
;
1454 DLIST_REMOVE(c
->request_queue
, req
);
1455 DLIST_ADD(c
->pending
, req
);
1456 req
->state
= RPC_REQUEST_PENDING
;
1458 init_ncacn_hdr(p
->conn
, &pkt
);
1460 remaining
= stub_data
->length
;
1462 /* we can write a full max_recv_frag size, minus the dcerpc
1463 request header size */
1464 chunk_size
= p
->conn
->srv_max_recv_frag
;
1465 chunk_size
-= DCERPC_REQUEST_LENGTH
;
1466 if (c
->security_state
.auth_info
&&
1467 c
->security_state
.generic_state
) {
1468 sig_size
= gensec_sig_size(c
->security_state
.generic_state
,
1469 p
->conn
->srv_max_recv_frag
);
1471 chunk_size
-= DCERPC_AUTH_TRAILER_LENGTH
;
1472 chunk_size
-= sig_size
;
1475 chunk_size
-= (chunk_size
% 16);
1477 pkt
.ptype
= DCERPC_PKT_REQUEST
;
1478 pkt
.call_id
= req
->call_id
;
1479 pkt
.auth_length
= 0;
1481 pkt
.u
.request
.alloc_hint
= remaining
;
1482 pkt
.u
.request
.context_id
= p
->context_id
;
1483 pkt
.u
.request
.opnum
= req
->opnum
;
1486 pkt
.u
.request
.object
.object
= *req
->object
;
1487 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_OBJECT_UUID
;
1488 chunk_size
-= ndr_size_GUID(req
->object
,0);
1491 /* we send a series of pdus without waiting for a reply */
1492 while (remaining
> 0 || first_packet
) {
1493 uint32_t chunk
= MIN(chunk_size
, remaining
);
1494 bool last_frag
= false;
1495 bool do_trans
= false;
1497 first_packet
= false;
1498 pkt
.pfc_flags
&= ~(DCERPC_PFC_FLAG_FIRST
|DCERPC_PFC_FLAG_LAST
);
1500 if (remaining
== stub_data
->length
) {
1501 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_FIRST
;
1503 if (chunk
== remaining
) {
1504 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_LAST
;
1508 pkt
.u
.request
.stub_and_verifier
.data
= stub_data
->data
+
1509 (stub_data
->length
- remaining
);
1510 pkt
.u
.request
.stub_and_verifier
.length
= chunk
;
1512 req
->status
= ncacn_push_request_sign(p
->conn
, &blob
, req
, sig_size
, &pkt
);
1513 if (!NT_STATUS_IS_OK(req
->status
)) {
1514 req
->state
= RPC_REQUEST_DONE
;
1515 DLIST_REMOVE(p
->conn
->pending
, req
);
1519 if (last_frag
&& !need_async
) {
1523 req
->status
= p
->conn
->transport
.send_request(p
->conn
, &blob
, do_trans
);
1524 if (!NT_STATUS_IS_OK(req
->status
)) {
1525 req
->state
= RPC_REQUEST_DONE
;
1526 DLIST_REMOVE(p
->conn
->pending
, req
);
1530 if (last_frag
&& !do_trans
) {
1531 req
->status
= p
->conn
->transport
.send_read(p
->conn
);
1532 if (!NT_STATUS_IS_OK(req
->status
)) {
1533 req
->state
= RPC_REQUEST_DONE
;
1534 DLIST_REMOVE(p
->conn
->pending
, req
);
1544 return the event context for a dcerpc pipe
1545 used by callers who wish to operate asynchronously
1547 _PUBLIC_
struct tevent_context
*dcerpc_event_context(struct dcerpc_pipe
*p
)
1549 return p
->conn
->event_ctx
;
1555 perform the receive side of a async dcerpc request
1557 static NTSTATUS
dcerpc_request_recv(struct rpc_request
*req
,
1558 TALLOC_CTX
*mem_ctx
,
1559 DATA_BLOB
*stub_data
)
1563 while (req
->state
!= RPC_REQUEST_DONE
) {
1564 struct tevent_context
*ctx
= dcerpc_event_context(req
->p
);
1565 if (event_loop_once(ctx
) != 0) {
1566 return NT_STATUS_CONNECTION_DISCONNECTED
;
1569 *stub_data
= req
->payload
;
1570 status
= req
->status
;
1571 if (stub_data
->data
) {
1572 stub_data
->data
= talloc_steal(mem_ctx
, stub_data
->data
);
1574 if (NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
1575 req
->p
->last_fault_code
= req
->fault_code
;
1577 talloc_unlink(talloc_parent(req
), req
);
1582 this is a paranoid NDR validator. For every packet we push onto the wire
1583 we pull it back again, then push it again. Then we compare the raw NDR data
1584 for that to the NDR we initially generated. If they don't match then we know
1585 we must have a bug in either the pull or push side of our code
1587 static NTSTATUS
dcerpc_ndr_validate_in(struct dcecli_connection
*c
,
1588 TALLOC_CTX
*mem_ctx
,
1591 ndr_push_flags_fn_t ndr_push
,
1592 ndr_pull_flags_fn_t ndr_pull
)
1595 struct ndr_pull
*pull
;
1596 struct ndr_push
*push
;
1598 enum ndr_err_code ndr_err
;
1600 st
= talloc_size(mem_ctx
, struct_size
);
1602 return NT_STATUS_NO_MEMORY
;
1605 pull
= ndr_pull_init_flags(c
, &blob
, mem_ctx
);
1607 return NT_STATUS_NO_MEMORY
;
1609 pull
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
1611 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
1612 pull
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
1615 if (c
->flags
& DCERPC_NDR64
) {
1616 pull
->flags
|= LIBNDR_FLAG_NDR64
;
1619 ndr_err
= ndr_pull(pull
, NDR_IN
, st
);
1620 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1621 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1622 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
1623 "failed input validation pull - %s",
1625 return ndr_map_error2ntstatus(ndr_err
);
1628 push
= ndr_push_init_ctx(mem_ctx
);
1630 return NT_STATUS_NO_MEMORY
;
1633 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
1634 push
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
1637 if (c
->flags
& DCERPC_NDR64
) {
1638 push
->flags
|= LIBNDR_FLAG_NDR64
;
1641 ndr_err
= ndr_push(push
, NDR_IN
, st
);
1642 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1643 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1644 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
1645 "failed input validation push - %s",
1647 return ndr_map_error2ntstatus(ndr_err
);
1650 blob2
= ndr_push_blob(push
);
1652 if (data_blob_cmp(&blob
, &blob2
) != 0) {
1653 DEBUG(3,("original:\n"));
1654 dump_data(3, blob
.data
, blob
.length
);
1655 DEBUG(3,("secondary:\n"));
1656 dump_data(3, blob2
.data
, blob2
.length
);
1657 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
1658 "failed input validation blobs doesn't match");
1659 return ndr_map_error2ntstatus(ndr_err
);
1662 return NT_STATUS_OK
;
1666 this is a paranoid NDR input validator. For every packet we pull
1667 from the wire we push it back again then pull and push it
1668 again. Then we compare the raw NDR data for that to the NDR we
1669 initially generated. If they don't match then we know we must have a
1670 bug in either the pull or push side of our code
1672 static NTSTATUS
dcerpc_ndr_validate_out(struct dcecli_connection
*c
,
1673 struct ndr_pull
*pull_in
,
1676 ndr_push_flags_fn_t ndr_push
,
1677 ndr_pull_flags_fn_t ndr_pull
,
1678 ndr_print_function_t ndr_print
)
1681 struct ndr_pull
*pull
;
1682 struct ndr_push
*push
;
1683 DATA_BLOB blob
, blob2
;
1684 TALLOC_CTX
*mem_ctx
= pull_in
;
1686 enum ndr_err_code ndr_err
;
1688 st
= talloc_size(mem_ctx
, struct_size
);
1690 return NT_STATUS_NO_MEMORY
;
1692 memcpy(st
, struct_ptr
, struct_size
);
1694 push
= ndr_push_init_ctx(mem_ctx
);
1696 return NT_STATUS_NO_MEMORY
;
1699 ndr_err
= ndr_push(push
, NDR_OUT
, struct_ptr
);
1700 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1701 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1702 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
1703 "failed output validation push - %s",
1705 return ndr_map_error2ntstatus(ndr_err
);
1708 blob
= ndr_push_blob(push
);
1710 pull
= ndr_pull_init_flags(c
, &blob
, mem_ctx
);
1712 return NT_STATUS_NO_MEMORY
;
1715 pull
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
1716 ndr_err
= ndr_pull(pull
, NDR_OUT
, st
);
1717 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1718 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1719 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
1720 "failed output validation pull - %s",
1722 return ndr_map_error2ntstatus(ndr_err
);
1725 push
= ndr_push_init_ctx(mem_ctx
);
1727 return NT_STATUS_NO_MEMORY
;
1730 ndr_err
= ndr_push(push
, NDR_OUT
, st
);
1731 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1732 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1733 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
1734 "failed output validation push2 - %s",
1736 return ndr_map_error2ntstatus(ndr_err
);
1739 blob2
= ndr_push_blob(push
);
1741 if (data_blob_cmp(&blob
, &blob2
) != 0) {
1742 DEBUG(3,("original:\n"));
1743 dump_data(3, blob
.data
, blob
.length
);
1744 DEBUG(3,("secondary:\n"));
1745 dump_data(3, blob2
.data
, blob2
.length
);
1746 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
1747 "failed output validation blobs doesn't match");
1748 return ndr_map_error2ntstatus(ndr_err
);
1751 /* this checks the printed forms of the two structures, which effectively
1752 tests all of the value() attributes */
1753 s1
= ndr_print_function_string(mem_ctx
, ndr_print
, "VALIDATE",
1754 NDR_OUT
, struct_ptr
);
1755 s2
= ndr_print_function_string(mem_ctx
, ndr_print
, "VALIDATE",
1757 if (strcmp(s1
, s2
) != 0) {
1759 DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1
, s2
));
1761 /* this is sometimes useful */
1762 printf("VALIDATE ERROR\n");
1763 file_save("wire.dat", s1
, strlen(s1
));
1764 file_save("gen.dat", s2
, strlen(s2
));
1765 system("diff -u wire.dat gen.dat");
1767 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
1768 "failed output validation strings doesn't match");
1769 return ndr_map_error2ntstatus(ndr_err
);
1772 return NT_STATUS_OK
;
1776 a useful function for retrieving the server name we connected to
1778 _PUBLIC_
const char *dcerpc_server_name(struct dcerpc_pipe
*p
)
1780 if (!p
->conn
->transport
.target_hostname
) {
1781 if (!p
->conn
->transport
.peer_name
) {
1784 return p
->conn
->transport
.peer_name(p
->conn
);
1786 return p
->conn
->transport
.target_hostname(p
->conn
);
1791 get the dcerpc auth_level for a open connection
1793 uint32_t dcerpc_auth_level(struct dcecli_connection
*c
)
1797 if (c
->flags
& DCERPC_SEAL
) {
1798 auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
1799 } else if (c
->flags
& DCERPC_SIGN
) {
1800 auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
1801 } else if (c
->flags
& DCERPC_CONNECT
) {
1802 auth_level
= DCERPC_AUTH_LEVEL_CONNECT
;
1804 auth_level
= DCERPC_AUTH_LEVEL_NONE
;
1810 Receive an alter reply from the transport
1812 static void dcerpc_alter_recv_handler(struct rpc_request
*req
,
1813 DATA_BLOB
*raw_packet
, struct ncacn_packet
*pkt
)
1815 struct composite_context
*c
;
1816 struct dcerpc_pipe
*recv_pipe
;
1818 c
= talloc_get_type(req
->async
.private_data
, struct composite_context
);
1819 recv_pipe
= talloc_get_type(c
->private_data
, struct dcerpc_pipe
);
1821 if (pkt
->ptype
== DCERPC_PKT_ALTER_RESP
&&
1822 pkt
->u
.alter_resp
.num_results
== 1 &&
1823 pkt
->u
.alter_resp
.ctx_list
[0].result
!= 0) {
1824 DEBUG(2,("dcerpc: alter_resp failed - reason %d\n",
1825 pkt
->u
.alter_resp
.ctx_list
[0].reason
));
1826 composite_error(c
, dcerpc_map_reason(pkt
->u
.alter_resp
.ctx_list
[0].reason
));
1830 if (pkt
->ptype
== DCERPC_PKT_FAULT
) {
1831 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c
, pkt
->u
.fault
.status
)));
1832 recv_pipe
->last_fault_code
= pkt
->u
.fault
.status
;
1833 composite_error(c
, NT_STATUS_NET_WRITE_FAULT
);
1837 if (pkt
->ptype
!= DCERPC_PKT_ALTER_RESP
||
1838 pkt
->u
.alter_resp
.num_results
== 0 ||
1839 pkt
->u
.alter_resp
.ctx_list
[0].result
!= 0) {
1840 recv_pipe
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
1841 composite_error(c
, NT_STATUS_NET_WRITE_FAULT
);
1845 /* the alter_resp might contain a reply set of credentials */
1846 if (recv_pipe
->conn
->security_state
.auth_info
&&
1847 pkt
->u
.alter_resp
.auth_info
.length
) {
1848 struct dcecli_connection
*conn
= recv_pipe
->conn
;
1850 uint32_t auth_length
;
1851 status
= dcerpc_pull_auth_trailer(pkt
, conn
, &pkt
->u
.alter_resp
.auth_info
,
1852 conn
->security_state
.auth_info
, &auth_length
, true);
1853 if (!NT_STATUS_IS_OK(status
)) {
1854 composite_error(c
, status
);
1863 send a dcerpc alter_context request
1865 struct composite_context
*dcerpc_alter_context_send(struct dcerpc_pipe
*p
,
1866 TALLOC_CTX
*mem_ctx
,
1867 const struct ndr_syntax_id
*syntax
,
1868 const struct ndr_syntax_id
*transfer_syntax
)
1870 struct composite_context
*c
;
1871 struct ncacn_packet pkt
;
1873 struct rpc_request
*req
;
1875 c
= composite_create(mem_ctx
, p
->conn
->event_ctx
);
1876 if (c
== NULL
) return NULL
;
1878 c
->private_data
= p
;
1880 p
->syntax
= *syntax
;
1881 p
->transfer_syntax
= *transfer_syntax
;
1883 init_ncacn_hdr(p
->conn
, &pkt
);
1885 pkt
.ptype
= DCERPC_PKT_ALTER
;
1886 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
1887 pkt
.call_id
= p
->conn
->call_id
;
1888 pkt
.auth_length
= 0;
1890 if (p
->binding
->flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
1891 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
1894 if (p
->binding
->flags
& DCERPC_HEADER_SIGNING
) {
1895 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
;
1898 pkt
.u
.alter
.max_xmit_frag
= 5840;
1899 pkt
.u
.alter
.max_recv_frag
= 5840;
1900 pkt
.u
.alter
.assoc_group_id
= p
->binding
->assoc_group_id
;
1901 pkt
.u
.alter
.num_contexts
= 1;
1902 pkt
.u
.alter
.ctx_list
= talloc_array(c
, struct dcerpc_ctx_list
, 1);
1903 if (composite_nomem(pkt
.u
.alter
.ctx_list
, c
)) return c
;
1904 pkt
.u
.alter
.ctx_list
[0].context_id
= p
->context_id
;
1905 pkt
.u
.alter
.ctx_list
[0].num_transfer_syntaxes
= 1;
1906 pkt
.u
.alter
.ctx_list
[0].abstract_syntax
= p
->syntax
;
1907 pkt
.u
.alter
.ctx_list
[0].transfer_syntaxes
= &p
->transfer_syntax
;
1908 pkt
.u
.alter
.auth_info
= data_blob(NULL
, 0);
1910 /* construct the NDR form of the packet */
1911 c
->status
= ncacn_push_auth(&blob
, mem_ctx
, &pkt
,
1912 p
->conn
->security_state
.auth_info
);
1913 if (!composite_is_ok(c
)) return c
;
1915 p
->conn
->transport
.recv_data
= dcerpc_recv_data
;
1918 * we allocate a dcerpc_request so we can be in the same
1919 * request queue as normal requests
1921 req
= talloc_zero(c
, struct rpc_request
);
1922 if (composite_nomem(req
, c
)) return c
;
1924 req
->state
= RPC_REQUEST_PENDING
;
1925 req
->call_id
= pkt
.call_id
;
1926 req
->async
.private_data
= c
;
1927 req
->async
.callback
= dcerpc_composite_fail
;
1929 req
->recv_handler
= dcerpc_alter_recv_handler
;
1930 DLIST_ADD_END(p
->conn
->pending
, req
, struct rpc_request
*);
1931 talloc_set_destructor(req
, dcerpc_req_dequeue
);
1933 c
->status
= p
->conn
->transport
.send_request(p
->conn
, &blob
, true);
1934 if (!composite_is_ok(c
)) return c
;
1936 event_add_timed(c
->event_ctx
, req
,
1937 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT
, 0),
1938 dcerpc_timeout_handler
, req
);
1943 NTSTATUS
dcerpc_alter_context_recv(struct composite_context
*ctx
)
1945 NTSTATUS result
= composite_wait(ctx
);
1951 send a dcerpc alter_context request
1953 _PUBLIC_ NTSTATUS
dcerpc_alter_context(struct dcerpc_pipe
*p
,
1954 TALLOC_CTX
*mem_ctx
,
1955 const struct ndr_syntax_id
*syntax
,
1956 const struct ndr_syntax_id
*transfer_syntax
)
1958 struct composite_context
*creq
;
1959 creq
= dcerpc_alter_context_send(p
, mem_ctx
, syntax
, transfer_syntax
);
1960 return dcerpc_alter_context_recv(creq
);