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/util_file.h"
25 #include "system/filesys.h"
26 #include "../lib/util/dlinklist.h"
27 #include "lib/events/events.h"
28 #include "librpc/rpc/dcerpc.h"
29 #include "librpc/rpc/dcerpc_proto.h"
30 #include "librpc/rpc/dcerpc_util.h"
31 #include "librpc/rpc/dcerpc_pkt_auth.h"
32 #include "librpc/gen_ndr/ndr_misc.h"
33 #include "librpc/gen_ndr/ndr_dcerpc.h"
34 #include "auth/gensec/gensec.h"
35 #include "param/param.h"
36 #include "lib/util/tevent_ntstatus.h"
37 #include "librpc/rpc/rpc_common.h"
38 #include "lib/tsocket/tsocket.h"
39 #include "libcli/smb/tstream_smbXcli_np.h"
42 enum rpc_request_state
{
49 handle for an async dcerpc request
52 struct rpc_request
*next
, *prev
;
53 struct dcerpc_pipe
*p
;
56 enum rpc_request_state state
;
61 /* this is used to distinguish bind and alter_context requests
62 from normal requests */
63 void (*recv_handler
)(struct rpc_request
*conn
,
64 DATA_BLOB
*blob
, struct ncacn_packet
*pkt
);
66 const struct GUID
*object
;
68 DATA_BLOB request_data
;
75 void (*callback
)(struct rpc_request
*);
80 _PUBLIC_ NTSTATUS
dcerpc_init(void)
85 static void dcerpc_connection_dead(struct dcecli_connection
*conn
, NTSTATUS status
);
86 static void dcerpc_schedule_io_trigger(struct dcecli_connection
*c
);
88 static struct rpc_request
*dcerpc_request_send(TALLOC_CTX
*mem_ctx
,
89 struct dcerpc_pipe
*p
,
90 const struct GUID
*object
,
92 DATA_BLOB
*stub_data
);
93 static NTSTATUS
dcerpc_request_recv(struct rpc_request
*req
,
95 DATA_BLOB
*stub_data
);
96 static NTSTATUS
dcerpc_ndr_validate_in(struct dcecli_connection
*c
,
100 ndr_push_flags_fn_t ndr_push
,
101 ndr_pull_flags_fn_t ndr_pull
);
102 static NTSTATUS
dcerpc_ndr_validate_out(struct dcecli_connection
*c
,
103 struct ndr_pull
*pull_in
,
106 ndr_push_flags_fn_t ndr_push
,
107 ndr_pull_flags_fn_t ndr_pull
,
108 ndr_print_function_t ndr_print
);
109 static NTSTATUS
dcerpc_shutdown_pipe(struct dcecli_connection
*p
, NTSTATUS status
);
110 static NTSTATUS
dcerpc_send_request(struct dcecli_connection
*p
, DATA_BLOB
*data
,
112 static NTSTATUS
dcerpc_send_read(struct dcecli_connection
*p
);
114 /* destroy a dcerpc connection */
115 static int dcerpc_connection_destructor(struct dcecli_connection
*conn
)
118 conn
->free_skipped
= true;
121 dcerpc_connection_dead(conn
, NT_STATUS_LOCAL_DISCONNECT
);
126 /* initialise a dcerpc connection.
127 the event context is optional
129 static struct dcecli_connection
*dcerpc_connection_init(TALLOC_CTX
*mem_ctx
,
130 struct tevent_context
*ev
)
132 struct dcecli_connection
*c
;
134 c
= talloc_zero(mem_ctx
, struct dcecli_connection
);
141 if (c
->event_ctx
== NULL
) {
147 c
->security_state
.auth_type
= DCERPC_AUTH_TYPE_NONE
;
148 c
->security_state
.auth_level
= DCERPC_AUTH_LEVEL_NONE
;
149 c
->security_state
.auth_context_id
= 0;
150 c
->security_state
.session_key
= dcecli_generic_session_key
;
151 c
->security_state
.generic_state
= NULL
;
154 * Windows uses 5840 for ncacn_ip_tcp,
155 * so we also use it (for every transport)
156 * by default. But we give the transport
157 * the chance to overwrite it.
159 c
->srv_max_xmit_frag
= 5840;
160 c
->srv_max_recv_frag
= 5840;
161 c
->max_total_response_size
= DCERPC_NCACN_RESPONSE_DEFAULT_MAX_SIZE
;
164 c
->io_trigger
= tevent_create_immediate(c
);
165 if (c
->io_trigger
== NULL
) {
170 talloc_set_destructor(c
, dcerpc_connection_destructor
);
175 struct dcerpc_bh_state
{
176 struct dcerpc_pipe
*p
;
179 static bool dcerpc_bh_is_connected(struct dcerpc_binding_handle
*h
)
181 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
182 struct dcerpc_bh_state
);
192 if (hs
->p
->conn
->dead
) {
199 static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle
*h
,
202 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
203 struct dcerpc_bh_state
);
207 return DCERPC_REQUEST_TIMEOUT
;
210 old
= hs
->p
->request_timeout
;
211 hs
->p
->request_timeout
= timeout
;
216 static void dcerpc_bh_auth_info(struct dcerpc_binding_handle
*h
,
217 enum dcerpc_AuthType
*auth_type
,
218 enum dcerpc_AuthLevel
*auth_level
)
220 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
221 struct dcerpc_bh_state
);
227 if (hs
->p
->conn
== NULL
) {
231 *auth_type
= hs
->p
->conn
->security_state
.auth_type
;
232 *auth_level
= hs
->p
->conn
->security_state
.auth_level
;
235 struct dcerpc_bh_raw_call_state
{
236 struct tevent_context
*ev
;
237 struct dcerpc_binding_handle
*h
;
243 static void dcerpc_bh_raw_call_done(struct rpc_request
*subreq
);
245 static struct tevent_req
*dcerpc_bh_raw_call_send(TALLOC_CTX
*mem_ctx
,
246 struct tevent_context
*ev
,
247 struct dcerpc_binding_handle
*h
,
248 const struct GUID
*object
,
251 const uint8_t *in_data
,
254 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
255 struct dcerpc_bh_state
);
256 struct tevent_req
*req
;
257 struct dcerpc_bh_raw_call_state
*state
;
259 struct rpc_request
*subreq
;
261 req
= tevent_req_create(mem_ctx
, &state
,
262 struct dcerpc_bh_raw_call_state
);
268 state
->in_data
.data
= discard_const_p(uint8_t, in_data
);
269 state
->in_data
.length
= in_length
;
271 ok
= dcerpc_bh_is_connected(h
);
273 tevent_req_nterror(req
, NT_STATUS_CONNECTION_DISCONNECTED
);
274 return tevent_req_post(req
, ev
);
277 subreq
= dcerpc_request_send(state
,
282 if (tevent_req_nomem(subreq
, req
)) {
283 return tevent_req_post(req
, ev
);
285 subreq
->async
.callback
= dcerpc_bh_raw_call_done
;
286 subreq
->async
.private_data
= req
;
291 static void dcerpc_bh_raw_call_done(struct rpc_request
*subreq
)
293 struct tevent_req
*req
=
294 talloc_get_type_abort(subreq
->async
.private_data
,
296 struct dcerpc_bh_raw_call_state
*state
=
298 struct dcerpc_bh_raw_call_state
);
302 state
->out_flags
= 0;
303 if (subreq
->flags
& DCERPC_PULL_BIGENDIAN
) {
304 state
->out_flags
|= LIBNDR_FLAG_BIGENDIAN
;
307 fault_code
= subreq
->fault_code
;
309 status
= dcerpc_request_recv(subreq
, state
, &state
->out_data
);
310 if (NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
311 status
= dcerpc_fault_to_nt_status(fault_code
);
315 * We trigger the callback in the next event run
316 * because the code in this file might trigger
317 * multiple request callbacks from within a single
320 * In order to avoid segfaults from within
321 * dcerpc_connection_dead() we call
322 * tevent_req_defer_callback().
324 tevent_req_defer_callback(req
, state
->ev
);
326 if (!NT_STATUS_IS_OK(status
)) {
327 tevent_req_nterror(req
, status
);
331 tevent_req_done(req
);
334 static NTSTATUS
dcerpc_bh_raw_call_recv(struct tevent_req
*req
,
340 struct dcerpc_bh_raw_call_state
*state
=
342 struct dcerpc_bh_raw_call_state
);
345 if (tevent_req_is_nterror(req
, &status
)) {
346 tevent_req_received(req
);
350 *out_data
= talloc_move(mem_ctx
, &state
->out_data
.data
);
351 *out_length
= state
->out_data
.length
;
352 *out_flags
= state
->out_flags
;
353 tevent_req_received(req
);
357 struct dcerpc_bh_disconnect_state
{
361 static struct tevent_req
*dcerpc_bh_disconnect_send(TALLOC_CTX
*mem_ctx
,
362 struct tevent_context
*ev
,
363 struct dcerpc_binding_handle
*h
)
365 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
366 struct dcerpc_bh_state
);
367 struct tevent_req
*req
;
368 struct dcerpc_bh_disconnect_state
*state
;
371 req
= tevent_req_create(mem_ctx
, &state
,
372 struct dcerpc_bh_disconnect_state
);
377 ok
= dcerpc_bh_is_connected(h
);
379 tevent_req_nterror(req
, NT_STATUS_CONNECTION_DISCONNECTED
);
380 return tevent_req_post(req
, ev
);
383 /* TODO: do a real disconnect ... */
386 tevent_req_done(req
);
387 return tevent_req_post(req
, ev
);
390 static NTSTATUS
dcerpc_bh_disconnect_recv(struct tevent_req
*req
)
394 if (tevent_req_is_nterror(req
, &status
)) {
395 tevent_req_received(req
);
399 tevent_req_received(req
);
403 static bool dcerpc_bh_push_bigendian(struct dcerpc_binding_handle
*h
)
405 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
406 struct dcerpc_bh_state
);
408 if (hs
->p
->conn
->flags
& DCERPC_PUSH_BIGENDIAN
) {
415 static bool dcerpc_bh_ref_alloc(struct dcerpc_binding_handle
*h
)
417 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
418 struct dcerpc_bh_state
);
420 if (hs
->p
->conn
->flags
& DCERPC_NDR_REF_ALLOC
) {
427 static bool dcerpc_bh_use_ndr64(struct dcerpc_binding_handle
*h
)
429 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
430 struct dcerpc_bh_state
);
432 if (hs
->p
->conn
->flags
& DCERPC_NDR64
) {
439 static void dcerpc_bh_do_ndr_print(struct dcerpc_binding_handle
*h
,
440 ndr_flags_type ndr_flags
,
441 const void *_struct_ptr
,
442 const struct ndr_interface_call
*call
)
444 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
445 struct dcerpc_bh_state
);
446 void *struct_ptr
= discard_const(_struct_ptr
);
447 bool print_in
= false;
448 bool print_out
= false;
450 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_PRINT_IN
) {
454 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_PRINT_OUT
) {
458 if (DEBUGLEVEL
>= 11) {
463 if (ndr_flags
& NDR_IN
) {
465 ndr_print_function_debug(call
->ndr_print
,
471 if (ndr_flags
& NDR_OUT
) {
473 ndr_print_function_debug(call
->ndr_print
,
481 static void dcerpc_bh_ndr_push_failed(struct dcerpc_binding_handle
*h
,
483 const void *struct_ptr
,
484 const struct ndr_interface_call
*call
)
486 DEBUG(2,("Unable to ndr_push structure for %s - %s\n",
487 call
->name
, nt_errstr(error
)));
490 static void dcerpc_bh_ndr_pull_failed(struct dcerpc_binding_handle
*h
,
492 const DATA_BLOB
*blob
,
493 const struct ndr_interface_call
*call
)
495 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
496 struct dcerpc_bh_state
);
497 const uint32_t num_examples
= 20;
500 DEBUG(2,("Unable to ndr_pull structure for %s - %s\n",
501 call
->name
, nt_errstr(error
)));
503 if (hs
->p
->conn
->packet_log_dir
== NULL
) return;
505 for (i
=0;i
<num_examples
;i
++) {
509 ret
= asprintf(&name
, "%s/rpclog/%s-out.%d",
510 hs
->p
->conn
->packet_log_dir
,
515 if (!file_exist(name
)) {
516 if (file_save(name
, blob
->data
, blob
->length
)) {
517 DEBUG(10,("Logged rpc packet to %s\n", name
));
526 static NTSTATUS
dcerpc_bh_ndr_validate_in(struct dcerpc_binding_handle
*h
,
528 const DATA_BLOB
*blob
,
529 const struct ndr_interface_call
*call
)
531 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
532 struct dcerpc_bh_state
);
534 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_VALIDATE_IN
) {
537 status
= dcerpc_ndr_validate_in(hs
->p
->conn
,
543 if (!NT_STATUS_IS_OK(status
)) {
544 DEBUG(0,("Validation [in] failed for %s - %s\n",
545 call
->name
, nt_errstr(status
)));
550 DEBUG(10,("rpc request data:\n"));
551 dump_data(10, blob
->data
, blob
->length
);
556 static NTSTATUS
dcerpc_bh_ndr_validate_out(struct dcerpc_binding_handle
*h
,
557 struct ndr_pull
*pull_in
,
558 const void *_struct_ptr
,
559 const struct ndr_interface_call
*call
)
561 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
562 struct dcerpc_bh_state
);
563 void *struct_ptr
= discard_const(_struct_ptr
);
565 DEBUG(10,("rpc reply data:\n"));
566 dump_data(10, pull_in
->data
, pull_in
->data_size
);
568 if (pull_in
->offset
!= pull_in
->data_size
) {
569 DEBUG(0,("Warning! ignoring %u unread bytes at ofs:%u (0x%08X) for %s!\n",
570 pull_in
->data_size
- pull_in
->offset
,
571 pull_in
->offset
, pull_in
->offset
,
573 /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here,
574 but it turns out that early versions of NT
575 (specifically NT3.1) add junk onto the end of rpc
576 packets, so if we want to interoperate at all with
577 those versions then we need to ignore this error */
580 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_VALIDATE_OUT
) {
583 status
= dcerpc_ndr_validate_out(hs
->p
->conn
,
590 if (!NT_STATUS_IS_OK(status
)) {
591 DEBUG(2,("Validation [out] failed for %s - %s\n",
592 call
->name
, nt_errstr(status
)));
600 static const struct dcerpc_binding_handle_ops dcerpc_bh_ops
= {
602 .is_connected
= dcerpc_bh_is_connected
,
603 .set_timeout
= dcerpc_bh_set_timeout
,
604 .auth_info
= dcerpc_bh_auth_info
,
605 .raw_call_send
= dcerpc_bh_raw_call_send
,
606 .raw_call_recv
= dcerpc_bh_raw_call_recv
,
607 .disconnect_send
= dcerpc_bh_disconnect_send
,
608 .disconnect_recv
= dcerpc_bh_disconnect_recv
,
610 .push_bigendian
= dcerpc_bh_push_bigendian
,
611 .ref_alloc
= dcerpc_bh_ref_alloc
,
612 .use_ndr64
= dcerpc_bh_use_ndr64
,
613 .do_ndr_print
= dcerpc_bh_do_ndr_print
,
614 .ndr_push_failed
= dcerpc_bh_ndr_push_failed
,
615 .ndr_pull_failed
= dcerpc_bh_ndr_pull_failed
,
616 .ndr_validate_in
= dcerpc_bh_ndr_validate_in
,
617 .ndr_validate_out
= dcerpc_bh_ndr_validate_out
,
620 /* initialise a dcerpc pipe. */
621 struct dcerpc_binding_handle
*dcerpc_pipe_binding_handle(struct dcerpc_pipe
*p
,
622 const struct GUID
*object
,
623 const struct ndr_interface_table
*table
)
625 struct dcerpc_binding_handle
*h
;
626 struct dcerpc_bh_state
*hs
;
628 h
= dcerpc_binding_handle_create(p
,
633 struct dcerpc_bh_state
,
640 dcerpc_binding_handle_set_sync_ev(h
, p
->conn
->event_ctx
);
645 /* initialise a dcerpc pipe. */
646 _PUBLIC_
struct dcerpc_pipe
*dcerpc_pipe_init(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
)
648 struct dcerpc_pipe
*p
;
650 p
= talloc_zero(mem_ctx
, struct dcerpc_pipe
);
655 p
->conn
= dcerpc_connection_init(p
, ev
);
656 if (p
->conn
== NULL
) {
661 p
->request_timeout
= DCERPC_REQUEST_TIMEOUT
;
664 p
->conn
->flags
|= DCERPC_DEBUG_PRINT_BOTH
;
672 choose the next call id to use
674 static uint32_t next_call_id(struct dcecli_connection
*c
)
677 if (c
->call_id
== 0) {
684 setup for a ndr pull, also setting up any flags from the binding string
686 static struct ndr_pull
*ndr_pull_init_flags(struct dcecli_connection
*c
,
687 DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
)
689 struct ndr_pull
*ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
691 if (ndr
== NULL
) return ndr
;
693 if (c
->flags
& DCERPC_DEBUG_PAD_CHECK
) {
694 ndr
->flags
|= LIBNDR_FLAG_PAD_CHECK
;
697 if (c
->flags
& DCERPC_NDR_REF_ALLOC
) {
698 ndr
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
701 if (c
->flags
& DCERPC_NDR64
) {
702 ndr
->flags
|= LIBNDR_FLAG_NDR64
;
709 parse the authentication information on a dcerpc response packet
711 static NTSTATUS
ncacn_pull_pkt_auth(struct dcecli_connection
*c
,
713 enum dcerpc_pkt_type ptype
,
714 uint8_t required_flags
,
715 uint8_t optional_flags
,
716 uint8_t payload_offset
,
717 DATA_BLOB
*payload_and_verifier
,
718 DATA_BLOB
*raw_packet
,
719 const struct ncacn_packet
*pkt
)
721 const struct dcerpc_auth tmp_auth
= {
722 .auth_type
= c
->security_state
.auth_type
,
723 .auth_level
= c
->security_state
.auth_level
,
724 .auth_context_id
= c
->security_state
.auth_context_id
,
728 status
= dcerpc_ncacn_pull_pkt_auth(&tmp_auth
,
729 c
->security_state
.generic_state
,
730 true, /* check_pkt_auth_fields */
736 payload_and_verifier
,
739 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROTOCOL_ERROR
)) {
740 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
742 if (!NT_STATUS_IS_OK(status
)) {
751 push a dcerpc request packet into a blob, possibly signing it.
753 static NTSTATUS
ncacn_push_request_sign(struct dcecli_connection
*c
,
754 DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
756 struct ncacn_packet
*pkt
)
758 const struct dcerpc_auth tmp_auth
= {
759 .auth_type
= c
->security_state
.auth_type
,
760 .auth_level
= c
->security_state
.auth_level
,
761 .auth_context_id
= c
->security_state
.auth_context_id
,
764 uint8_t payload_offset
= DCERPC_REQUEST_LENGTH
;
766 if (pkt
->pfc_flags
& DCERPC_PFC_FLAG_OBJECT_UUID
) {
767 payload_offset
+= 16;
770 status
= dcerpc_ncacn_push_pkt_auth(&tmp_auth
,
771 c
->security_state
.generic_state
,
775 &pkt
->u
.request
.stub_and_verifier
,
777 if (!NT_STATUS_IS_OK(status
)) {
786 fill in the fixed values in a dcerpc header
788 static void init_ncacn_hdr(struct dcecli_connection
*c
, struct ncacn_packet
*pkt
)
791 pkt
->rpc_vers_minor
= 0;
792 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
795 pkt
->drep
[0] = DCERPC_DREP_LE
;
803 map a bind nak reason to a NTSTATUS
805 static NTSTATUS
dcerpc_map_nak_reason(enum dcerpc_bind_nak_reason reason
)
808 case DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED
:
809 return NT_STATUS_REVISION_MISMATCH
;
810 case DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE
:
811 return NT_STATUS_INVALID_PARAMETER
;
815 return NT_STATUS_UNSUCCESSFUL
;
818 static NTSTATUS
dcerpc_map_ack_reason(const struct dcerpc_ack_ctx
*ack
)
821 return NT_STATUS_RPC_PROTOCOL_ERROR
;
824 switch (ack
->result
) {
825 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK
:
827 * We have not asked for this...
829 return NT_STATUS_RPC_PROTOCOL_ERROR
;
834 switch (ack
->reason
.value
) {
835 case DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED
:
836 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX
;
837 case DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED
:
838 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX
;
842 return NT_STATUS_UNSUCCESSFUL
;
846 remove requests from the pending or queued queues
848 static int dcerpc_req_dequeue(struct rpc_request
*req
)
850 switch (req
->state
) {
851 case RPC_REQUEST_QUEUED
:
852 DLIST_REMOVE(req
->p
->conn
->request_queue
, req
);
854 case RPC_REQUEST_PENDING
:
855 DLIST_REMOVE(req
->p
->conn
->pending
, req
);
857 case RPC_REQUEST_DONE
:
865 mark the dcerpc connection dead. All outstanding requests get an error
867 static void dcerpc_connection_dead(struct dcecli_connection
*conn
, NTSTATUS status
)
869 if (conn
->dead
) return;
873 TALLOC_FREE(conn
->io_trigger
);
874 conn
->io_trigger_pending
= false;
876 dcerpc_shutdown_pipe(conn
, status
);
878 /* all pending requests get the error */
879 while (conn
->pending
) {
880 struct rpc_request
*req
= conn
->pending
;
881 dcerpc_req_dequeue(req
);
882 req
->state
= RPC_REQUEST_DONE
;
883 req
->status
= status
;
884 if (req
->async
.callback
) {
885 req
->async
.callback(req
);
889 /* all requests, which are not shipped */
890 while (conn
->request_queue
) {
891 struct rpc_request
*req
= conn
->request_queue
;
892 dcerpc_req_dequeue(req
);
893 req
->state
= RPC_REQUEST_DONE
;
894 req
->status
= status
;
895 if (req
->async
.callback
) {
896 req
->async
.callback(req
);
900 talloc_set_destructor(conn
, NULL
);
901 if (conn
->free_skipped
) {
907 forward declarations of the recv_data handlers for the types of
908 packets we need to handle
910 static void dcerpc_request_recv_data(struct dcecli_connection
*c
,
911 DATA_BLOB
*raw_packet
, struct ncacn_packet
*pkt
);
914 receive a dcerpc reply from the transport. Here we work out what
915 type of reply it is (normal request, bind or alter context) and
916 dispatch to the appropriate handler
918 static void dcerpc_recv_data(struct dcecli_connection
*conn
, DATA_BLOB
*blob
, NTSTATUS status
)
920 struct ncacn_packet pkt
;
926 if (NT_STATUS_IS_OK(status
) && blob
->length
== 0) {
927 status
= NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
930 /* the transport may be telling us of a severe error, such as
932 if (!NT_STATUS_IS_OK(status
)) {
933 data_blob_free(blob
);
934 dcerpc_connection_dead(conn
, status
);
938 /* parse the basic packet to work out what type of response this is */
939 status
= dcerpc_pull_ncacn_packet(blob
->data
, blob
, &pkt
);
940 if (!NT_STATUS_IS_OK(status
)) {
941 data_blob_free(blob
);
942 dcerpc_connection_dead(conn
, status
);
946 dcerpc_request_recv_data(conn
, blob
, &pkt
);
950 handle timeouts of individual dcerpc requests
952 static void dcerpc_timeout_handler(struct tevent_context
*ev
, struct tevent_timer
*te
,
953 struct timeval t
, void *private_data
)
955 struct rpc_request
*req
= talloc_get_type(private_data
, struct rpc_request
);
957 if (req
->ignore_timeout
) {
958 dcerpc_req_dequeue(req
);
959 req
->state
= RPC_REQUEST_DONE
;
960 req
->status
= NT_STATUS_IO_TIMEOUT
;
961 if (req
->async
.callback
) {
962 req
->async
.callback(req
);
967 dcerpc_connection_dead(req
->p
->conn
, NT_STATUS_IO_TIMEOUT
);
970 struct dcerpc_bind_state
{
971 struct tevent_context
*ev
;
972 struct dcerpc_pipe
*p
;
975 static void dcerpc_bind_fail_handler(struct rpc_request
*subreq
);
976 static void dcerpc_bind_recv_handler(struct rpc_request
*subreq
,
977 DATA_BLOB
*raw_packet
,
978 struct ncacn_packet
*pkt
);
980 struct tevent_req
*dcerpc_bind_send(TALLOC_CTX
*mem_ctx
,
981 struct tevent_context
*ev
,
982 struct dcerpc_pipe
*p
,
983 const struct ndr_syntax_id
*syntax
,
984 const struct ndr_syntax_id
*transfer_syntax
)
986 struct tevent_req
*req
;
987 struct dcerpc_bind_state
*state
;
988 struct ncacn_packet pkt
;
991 struct rpc_request
*subreq
;
993 struct ndr_syntax_id bind_time_features
;
995 bind_time_features
= dcerpc_construct_bind_time_features(
996 DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING
|
997 DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN
);
999 req
= tevent_req_create(mem_ctx
, &state
,
1000 struct dcerpc_bind_state
);
1008 p
->syntax
= *syntax
;
1009 p
->transfer_syntax
= *transfer_syntax
;
1011 flags
= dcerpc_binding_get_flags(p
->binding
);
1013 init_ncacn_hdr(p
->conn
, &pkt
);
1015 pkt
.ptype
= DCERPC_PKT_BIND
;
1016 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
1017 pkt
.call_id
= p
->conn
->call_id
;
1018 pkt
.auth_length
= 0;
1020 if (flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
1021 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
1024 if (p
->conn
->flags
& DCERPC_PROPOSE_HEADER_SIGNING
) {
1025 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
;
1028 pkt
.u
.bind
.max_xmit_frag
= p
->conn
->srv_max_xmit_frag
;
1029 pkt
.u
.bind
.max_recv_frag
= p
->conn
->srv_max_recv_frag
;
1030 pkt
.u
.bind
.assoc_group_id
= dcerpc_binding_get_assoc_group_id(p
->binding
);
1031 pkt
.u
.bind
.num_contexts
= 2;
1032 pkt
.u
.bind
.ctx_list
= talloc_zero_array(state
, struct dcerpc_ctx_list
,
1033 pkt
.u
.bind
.num_contexts
);
1034 if (tevent_req_nomem(pkt
.u
.bind
.ctx_list
, req
)) {
1035 return tevent_req_post(req
, ev
);
1037 pkt
.u
.bind
.ctx_list
[0].context_id
= p
->context_id
;
1038 pkt
.u
.bind
.ctx_list
[0].num_transfer_syntaxes
= 1;
1039 pkt
.u
.bind
.ctx_list
[0].abstract_syntax
= p
->syntax
;
1040 pkt
.u
.bind
.ctx_list
[0].transfer_syntaxes
= &p
->transfer_syntax
;
1041 pkt
.u
.bind
.ctx_list
[1].context_id
= p
->context_id
+ 1;
1042 pkt
.u
.bind
.ctx_list
[1].num_transfer_syntaxes
= 1;
1043 pkt
.u
.bind
.ctx_list
[1].abstract_syntax
= p
->syntax
;
1044 pkt
.u
.bind
.ctx_list
[1].transfer_syntaxes
= &bind_time_features
;
1045 pkt
.u
.bind
.auth_info
= data_blob(NULL
, 0);
1047 /* construct the NDR form of the packet */
1048 status
= dcerpc_ncacn_push_auth(&blob
,
1051 p
->conn
->security_state
.tmp_auth_info
.out
);
1052 if (tevent_req_nterror(req
, status
)) {
1053 return tevent_req_post(req
, ev
);
1057 * we allocate a dcerpc_request so we can be in the same
1058 * request queue as normal requests
1060 subreq
= talloc_zero(state
, struct rpc_request
);
1061 if (tevent_req_nomem(subreq
, req
)) {
1062 return tevent_req_post(req
, ev
);
1065 subreq
->state
= RPC_REQUEST_PENDING
;
1066 subreq
->call_id
= pkt
.call_id
;
1067 subreq
->async
.private_data
= req
;
1068 subreq
->async
.callback
= dcerpc_bind_fail_handler
;
1070 subreq
->recv_handler
= dcerpc_bind_recv_handler
;
1071 DLIST_ADD_END(p
->conn
->pending
, subreq
);
1072 talloc_set_destructor(subreq
, dcerpc_req_dequeue
);
1074 status
= dcerpc_send_request(p
->conn
, &blob
, true);
1075 if (tevent_req_nterror(req
, status
)) {
1076 return tevent_req_post(req
, ev
);
1079 tevent_add_timer(ev
, subreq
,
1080 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT
, 0),
1081 dcerpc_timeout_handler
, subreq
);
1086 static void dcerpc_bind_fail_handler(struct rpc_request
*subreq
)
1088 struct tevent_req
*req
=
1089 talloc_get_type_abort(subreq
->async
.private_data
,
1091 struct dcerpc_bind_state
*state
=
1092 tevent_req_data(req
,
1093 struct dcerpc_bind_state
);
1094 NTSTATUS status
= subreq
->status
;
1096 TALLOC_FREE(subreq
);
1099 * We trigger the callback in the next event run
1100 * because the code in this file might trigger
1101 * multiple request callbacks from within a single
1104 * In order to avoid segfaults from within
1105 * dcerpc_connection_dead() we call
1106 * tevent_req_defer_callback().
1108 tevent_req_defer_callback(req
, state
->ev
);
1110 tevent_req_nterror(req
, status
);
1113 static void dcerpc_bind_recv_handler(struct rpc_request
*subreq
,
1114 DATA_BLOB
*raw_packet
,
1115 struct ncacn_packet
*pkt
)
1117 struct tevent_req
*req
=
1118 talloc_get_type_abort(subreq
->async
.private_data
,
1120 struct dcerpc_bind_state
*state
=
1121 tevent_req_data(req
,
1122 struct dcerpc_bind_state
);
1123 struct dcecli_connection
*conn
= state
->p
->conn
;
1124 struct dcecli_security
*sec
= &conn
->security_state
;
1125 struct dcerpc_binding
*b
= NULL
;
1130 * Note that pkt is allocated under raw_packet->data,
1131 * while raw_packet->data is a child of subreq.
1133 talloc_steal(state
, raw_packet
->data
);
1134 TALLOC_FREE(subreq
);
1137 * We trigger the callback in the next event run
1138 * because the code in this file might trigger
1139 * multiple request callbacks from within a single
1142 * In order to avoid segfaults from within
1143 * dcerpc_connection_dead() we call
1144 * tevent_req_defer_callback().
1146 tevent_req_defer_callback(req
, state
->ev
);
1148 if (pkt
->ptype
== DCERPC_PKT_BIND_NAK
) {
1149 status
= dcerpc_map_nak_reason(pkt
->u
.bind_nak
.reject_reason
);
1151 DEBUG(2,("dcerpc: bind_nak reason %d - %s\n",
1152 pkt
->u
.bind_nak
.reject_reason
, nt_errstr(status
)));
1154 tevent_req_nterror(req
, status
);
1158 status
= dcerpc_verify_ncacn_packet_header(pkt
,
1159 DCERPC_PKT_BIND_ACK
,
1160 pkt
->u
.bind_ack
.auth_info
.length
,
1161 DCERPC_PFC_FLAG_FIRST
|
1162 DCERPC_PFC_FLAG_LAST
,
1163 DCERPC_PFC_FLAG_CONC_MPX
|
1164 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
);
1165 if (!NT_STATUS_IS_OK(status
)) {
1166 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
1167 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
1171 if (pkt
->u
.bind_ack
.num_results
< 1) {
1172 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
1173 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
1177 if (pkt
->u
.bind_ack
.ctx_list
[0].result
!= 0) {
1178 status
= dcerpc_map_ack_reason(&pkt
->u
.bind_ack
.ctx_list
[0]);
1179 DEBUG(2,("dcerpc: bind_ack failed - reason %d - %s\n",
1180 pkt
->u
.bind_ack
.ctx_list
[0].reason
.value
,
1181 nt_errstr(status
)));
1182 tevent_req_nterror(req
, status
);
1186 if (pkt
->u
.bind_ack
.num_results
>= 2) {
1187 if (pkt
->u
.bind_ack
.ctx_list
[1].result
== DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK
) {
1188 conn
->bind_time_features
= pkt
->u
.bind_ack
.ctx_list
[1].reason
.negotiate
;
1190 status
= dcerpc_map_ack_reason(&pkt
->u
.bind_ack
.ctx_list
[1]);
1191 DEBUG(10,("dcerpc: bind_time_feature failed - reason %d - %s\n",
1192 pkt
->u
.bind_ack
.ctx_list
[1].reason
.value
,
1193 nt_errstr(status
)));
1194 status
= NT_STATUS_OK
;
1199 * DCE-RPC 1.1 (c706) specifies
1200 * CONST_MUST_RCV_FRAG_SIZE as 1432
1202 if (pkt
->u
.bind_ack
.max_xmit_frag
< 1432) {
1203 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
1204 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
1207 if (pkt
->u
.bind_ack
.max_recv_frag
< 1432) {
1208 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
1209 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
1212 conn
->srv_max_xmit_frag
= MIN(conn
->srv_max_xmit_frag
,
1213 pkt
->u
.bind_ack
.max_xmit_frag
);
1214 conn
->srv_max_recv_frag
= MIN(conn
->srv_max_recv_frag
,
1215 pkt
->u
.bind_ack
.max_recv_frag
);
1217 flags
= dcerpc_binding_get_flags(state
->p
->binding
);
1219 if (flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
1220 if (pkt
->pfc_flags
& DCERPC_PFC_FLAG_CONC_MPX
) {
1221 conn
->flags
|= DCERPC_CONCURRENT_MULTIPLEX
;
1223 conn
->flags
&= ~DCERPC_CONCURRENT_MULTIPLEX
;
1227 if (!(conn
->flags
& DCERPC_CONCURRENT_MULTIPLEX
)) {
1228 struct dcerpc_binding
*pb
=
1229 discard_const_p(struct dcerpc_binding
, state
->p
->binding
);
1231 * clear DCERPC_CONCURRENT_MULTIPLEX
1233 status
= dcerpc_binding_set_flags(pb
, 0,
1234 DCERPC_CONCURRENT_MULTIPLEX
);
1235 if (tevent_req_nterror(req
, status
)) {
1239 if ((conn
->flags
& DCERPC_PROPOSE_HEADER_SIGNING
) &&
1240 (pkt
->pfc_flags
& DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
)) {
1241 conn
->flags
|= DCERPC_HEADER_SIGNING
;
1244 /* the bind_ack might contain a reply set of credentials */
1245 if (pkt
->auth_length
!= 0 && sec
->tmp_auth_info
.in
!= NULL
) {
1246 status
= dcerpc_pull_auth_trailer(pkt
, sec
->tmp_auth_info
.mem
,
1247 &pkt
->u
.bind_ack
.auth_info
,
1248 sec
->tmp_auth_info
.in
,
1250 if (tevent_req_nterror(req
, status
)) {
1256 * We're the owner of the binding, so we're allowed to modify it.
1258 b
= discard_const_p(struct dcerpc_binding
, state
->p
->binding
);
1259 status
= dcerpc_binding_set_assoc_group_id(b
,
1260 pkt
->u
.bind_ack
.assoc_group_id
);
1261 if (tevent_req_nterror(req
, status
)) {
1265 tevent_req_done(req
);
1268 NTSTATUS
dcerpc_bind_recv(struct tevent_req
*req
)
1270 return tevent_req_simple_recv_ntstatus(req
);
1274 perform a continued bind (and auth3)
1276 NTSTATUS
dcerpc_auth3(struct dcerpc_pipe
*p
,
1277 TALLOC_CTX
*mem_ctx
)
1279 struct ncacn_packet pkt
;
1284 flags
= dcerpc_binding_get_flags(p
->binding
);
1286 init_ncacn_hdr(p
->conn
, &pkt
);
1288 pkt
.ptype
= DCERPC_PKT_AUTH3
;
1289 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
1290 pkt
.call_id
= next_call_id(p
->conn
);
1291 pkt
.auth_length
= 0;
1292 pkt
.u
.auth3
.auth_info
= data_blob(NULL
, 0);
1294 if (flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
1295 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
1298 /* construct the NDR form of the packet */
1299 status
= dcerpc_ncacn_push_auth(&blob
,
1302 p
->conn
->security_state
.tmp_auth_info
.out
);
1303 if (!NT_STATUS_IS_OK(status
)) {
1307 /* send it on its way */
1308 status
= dcerpc_send_request(p
->conn
, &blob
, false);
1309 if (!NT_STATUS_IS_OK(status
)) {
1313 return NT_STATUS_OK
;
1318 process a fragment received from the transport layer during a
1321 This function frees the data
1323 static void dcerpc_request_recv_data(struct dcecli_connection
*c
,
1324 DATA_BLOB
*raw_packet
, struct ncacn_packet
*pkt
)
1326 struct rpc_request
*req
;
1327 unsigned int length
;
1328 NTSTATUS status
= NT_STATUS_OK
;
1331 if this is an authenticated connection then parse and check
1332 the auth info. We have to do this before finding the
1333 matching packet, as the request structure might have been
1334 removed due to a timeout, but if it has been we still need
1335 to run the auth routines so that we don't get the sign/seal
1336 info out of step with the server
1338 switch (pkt
->ptype
) {
1339 case DCERPC_PKT_RESPONSE
:
1340 status
= ncacn_pull_pkt_auth(c
, raw_packet
->data
,
1341 DCERPC_PKT_RESPONSE
,
1342 0, /* required_flags */
1343 DCERPC_PFC_FLAG_FIRST
|
1344 DCERPC_PFC_FLAG_LAST
,
1345 DCERPC_REQUEST_LENGTH
,
1346 &pkt
->u
.response
.stub_and_verifier
,
1353 /* find the matching request */
1354 for (req
=c
->pending
;req
;req
=req
->next
) {
1355 if (pkt
->call_id
== req
->call_id
) break;
1359 /* useful for testing certain vendors RPC servers */
1360 if (req
== NULL
&& c
->pending
&& pkt
->call_id
== 0) {
1361 DEBUG(0,("HACK FOR INCORRECT CALL ID\n"));
1367 DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt
->call_id
));
1368 data_blob_free(raw_packet
);
1372 talloc_steal(req
, raw_packet
->data
);
1374 if (req
->recv_handler
!= NULL
) {
1375 dcerpc_req_dequeue(req
);
1376 req
->state
= RPC_REQUEST_DONE
;
1379 * We have to look at shipping further requests before calling
1380 * the async function, that one might close the pipe
1382 dcerpc_schedule_io_trigger(c
);
1384 req
->recv_handler(req
, raw_packet
, pkt
);
1388 if (pkt
->ptype
== DCERPC_PKT_FAULT
) {
1389 status
= dcerpc_fault_to_nt_status(pkt
->u
.fault
.status
);
1390 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c
, pkt
->u
.fault
.status
)));
1391 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROTOCOL_ERROR
)) {
1392 dcerpc_connection_dead(c
, status
);
1395 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1396 dcerpc_connection_dead(c
, status
);
1399 req
->fault_code
= pkt
->u
.fault
.status
;
1400 req
->status
= NT_STATUS_NET_WRITE_FAULT
;
1404 if (pkt
->ptype
!= DCERPC_PKT_RESPONSE
) {
1405 DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
1407 dcerpc_connection_dead(c
, NT_STATUS_RPC_PROTOCOL_ERROR
);
1411 /* now check the status from the auth routines, and if it failed then fail
1412 this request accordingly */
1413 if (!NT_STATUS_IS_OK(status
)) {
1414 dcerpc_connection_dead(c
, status
);
1418 length
= pkt
->u
.response
.stub_and_verifier
.length
;
1420 if (req
->payload
.length
+ length
> c
->max_total_response_size
) {
1421 DEBUG(2,("Unexpected total payload 0x%X > 0x%X dcerpc response\n",
1422 (unsigned)req
->payload
.length
+ length
,
1423 (unsigned)c
->max_total_response_size
));
1424 dcerpc_connection_dead(c
, NT_STATUS_RPC_PROTOCOL_ERROR
);
1429 req
->payload
.data
= talloc_realloc(req
,
1432 req
->payload
.length
+ length
);
1433 if (!req
->payload
.data
) {
1434 req
->status
= NT_STATUS_NO_MEMORY
;
1437 memcpy(req
->payload
.data
+req
->payload
.length
,
1438 pkt
->u
.response
.stub_and_verifier
.data
, length
);
1439 req
->payload
.length
+= length
;
1442 if (!(pkt
->pfc_flags
& DCERPC_PFC_FLAG_LAST
)) {
1443 data_blob_free(raw_packet
);
1444 dcerpc_send_read(c
);
1448 if (req
->verify_bitmask1
) {
1449 req
->p
->conn
->security_state
.verified_bitmask1
= true;
1451 if (req
->verify_pcontext
) {
1452 req
->p
->verified_pcontext
= true;
1455 if (!(pkt
->drep
[0] & DCERPC_DREP_LE
)) {
1456 req
->flags
|= DCERPC_PULL_BIGENDIAN
;
1458 req
->flags
&= ~DCERPC_PULL_BIGENDIAN
;
1462 data_blob_free(raw_packet
);
1464 /* we've got the full payload */
1465 dcerpc_req_dequeue(req
);
1466 req
->state
= RPC_REQUEST_DONE
;
1469 * We have to look at shipping further requests before calling
1470 * the async function, that one might close the pipe
1472 dcerpc_schedule_io_trigger(c
);
1474 if (req
->async
.callback
) {
1475 req
->async
.callback(req
);
1479 static NTSTATUS
dcerpc_request_prepare_vt(struct rpc_request
*req
);
1482 perform the send side of a async dcerpc request
1484 static struct rpc_request
*dcerpc_request_send(TALLOC_CTX
*mem_ctx
,
1485 struct dcerpc_pipe
*p
,
1486 const struct GUID
*object
,
1488 DATA_BLOB
*stub_data
)
1490 struct rpc_request
*req
;
1493 req
= talloc_zero(mem_ctx
, struct rpc_request
);
1499 req
->call_id
= next_call_id(p
->conn
);
1500 req
->state
= RPC_REQUEST_QUEUED
;
1502 if (object
!= NULL
) {
1503 req
->object
= (struct GUID
*)talloc_memdup(req
, (const void *)object
, sizeof(*object
));
1504 if (req
->object
== NULL
) {
1511 req
->request_data
.length
= stub_data
->length
;
1512 req
->request_data
.data
= stub_data
->data
;
1514 status
= dcerpc_request_prepare_vt(req
);
1515 if (!NT_STATUS_IS_OK(status
)) {
1520 DLIST_ADD_END(p
->conn
->request_queue
, req
);
1521 talloc_set_destructor(req
, dcerpc_req_dequeue
);
1523 dcerpc_schedule_io_trigger(p
->conn
);
1525 if (p
->request_timeout
) {
1526 tevent_add_timer(p
->conn
->event_ctx
, req
,
1527 timeval_current_ofs(p
->request_timeout
, 0),
1528 dcerpc_timeout_handler
, req
);
1534 static NTSTATUS
dcerpc_request_prepare_vt(struct rpc_request
*req
)
1536 struct dcecli_security
*sec
= &req
->p
->conn
->security_state
;
1537 struct dcerpc_sec_verification_trailer
*t
;
1538 struct dcerpc_sec_vt
*c
= NULL
;
1539 struct ndr_push
*ndr
= NULL
;
1540 enum ndr_err_code ndr_err
;
1542 if (sec
->auth_level
< DCERPC_AUTH_LEVEL_PACKET
) {
1543 return NT_STATUS_OK
;
1546 t
= talloc_zero(req
, struct dcerpc_sec_verification_trailer
);
1548 return NT_STATUS_NO_MEMORY
;
1551 if (!sec
->verified_bitmask1
) {
1552 t
->commands
= talloc_realloc(t
, t
->commands
,
1553 struct dcerpc_sec_vt
,
1554 t
->count
.count
+ 1);
1555 if (t
->commands
== NULL
) {
1556 return NT_STATUS_NO_MEMORY
;
1558 c
= &t
->commands
[t
->count
.count
++];
1561 c
->command
= DCERPC_SEC_VT_COMMAND_BITMASK1
;
1562 if (req
->p
->conn
->flags
& DCERPC_PROPOSE_HEADER_SIGNING
) {
1563 c
->u
.bitmask1
= DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING
;
1565 req
->verify_bitmask1
= true;
1568 if (!req
->p
->verified_pcontext
) {
1569 t
->commands
= talloc_realloc(t
, t
->commands
,
1570 struct dcerpc_sec_vt
,
1571 t
->count
.count
+ 1);
1572 if (t
->commands
== NULL
) {
1573 return NT_STATUS_NO_MEMORY
;
1575 c
= &t
->commands
[t
->count
.count
++];
1578 c
->command
= DCERPC_SEC_VT_COMMAND_PCONTEXT
;
1579 c
->u
.pcontext
.abstract_syntax
= req
->p
->syntax
;
1580 c
->u
.pcontext
.transfer_syntax
= req
->p
->transfer_syntax
;
1582 req
->verify_pcontext
= true;
1585 if (!(req
->p
->conn
->flags
& DCERPC_HEADER_SIGNING
)) {
1586 t
->commands
= talloc_realloc(t
, t
->commands
,
1587 struct dcerpc_sec_vt
,
1588 t
->count
.count
+ 1);
1589 if (t
->commands
== NULL
) {
1590 return NT_STATUS_NO_MEMORY
;
1592 c
= &t
->commands
[t
->count
.count
++];
1595 c
->command
= DCERPC_SEC_VT_COMMAND_HEADER2
;
1596 c
->u
.header2
.ptype
= DCERPC_PKT_REQUEST
;
1597 if (req
->p
->conn
->flags
& DCERPC_PUSH_BIGENDIAN
) {
1598 c
->u
.header2
.drep
[0] = 0;
1600 c
->u
.header2
.drep
[0] = DCERPC_DREP_LE
;
1602 c
->u
.header2
.drep
[1] = 0;
1603 c
->u
.header2
.drep
[2] = 0;
1604 c
->u
.header2
.drep
[3] = 0;
1605 c
->u
.header2
.call_id
= req
->call_id
;
1606 c
->u
.header2
.context_id
= req
->p
->context_id
;
1607 c
->u
.header2
.opnum
= req
->opnum
;
1610 if (t
->count
.count
== 0) {
1612 return NT_STATUS_OK
;
1615 c
= &t
->commands
[t
->count
.count
- 1];
1616 c
->command
|= DCERPC_SEC_VT_COMMAND_END
;
1618 if (DEBUGLEVEL
>= 10) {
1619 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer
, t
);
1622 ndr
= ndr_push_init_ctx(req
);
1624 return NT_STATUS_NO_MEMORY
;
1628 * for now we just copy and append
1631 ndr_err
= ndr_push_bytes(ndr
, req
->request_data
.data
,
1632 req
->request_data
.length
);
1633 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1634 return ndr_map_error2ntstatus(ndr_err
);
1637 ndr_err
= ndr_push_dcerpc_sec_verification_trailer(ndr
,
1638 NDR_SCALARS
| NDR_BUFFERS
,
1640 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1641 return ndr_map_error2ntstatus(ndr_err
);
1643 req
->request_data
= ndr_push_blob(ndr
);
1645 return NT_STATUS_OK
;
1649 Send a request using the transport
1652 static void dcerpc_ship_next_request(struct dcecli_connection
*c
)
1654 struct rpc_request
*req
;
1655 struct dcerpc_pipe
*p
;
1656 DATA_BLOB
*stub_data
;
1657 struct ncacn_packet pkt
;
1659 uint32_t remaining
, chunk_size
;
1660 bool first_packet
= true;
1661 size_t sig_size
= 0;
1662 bool need_async
= false;
1663 bool can_async
= true;
1665 req
= c
->request_queue
;
1671 stub_data
= &req
->request_data
;
1677 if (c
->security_state
.auth_level
>= DCERPC_AUTH_LEVEL_PACKET
) {
1678 can_async
= gensec_have_feature(c
->security_state
.generic_state
,
1679 GENSEC_FEATURE_ASYNC_REPLIES
);
1682 if (need_async
&& !can_async
) {
1683 req
->wait_for_sync
= true;
1687 DLIST_REMOVE(c
->request_queue
, req
);
1688 DLIST_ADD(c
->pending
, req
);
1689 req
->state
= RPC_REQUEST_PENDING
;
1691 init_ncacn_hdr(p
->conn
, &pkt
);
1693 remaining
= stub_data
->length
;
1695 /* we can write a full max_recv_frag size, minus the dcerpc
1696 request header size */
1697 chunk_size
= p
->conn
->srv_max_recv_frag
;
1698 chunk_size
-= DCERPC_REQUEST_LENGTH
;
1699 if (c
->security_state
.auth_level
>= DCERPC_AUTH_LEVEL_PACKET
) {
1700 size_t max_payload
= chunk_size
;
1702 max_payload
-= DCERPC_AUTH_TRAILER_LENGTH
;
1703 max_payload
-= (max_payload
% DCERPC_AUTH_PAD_ALIGNMENT
);
1705 sig_size
= gensec_sig_size(c
->security_state
.generic_state
,
1708 chunk_size
-= DCERPC_AUTH_TRAILER_LENGTH
;
1709 chunk_size
-= sig_size
;
1712 chunk_size
-= (chunk_size
% DCERPC_AUTH_PAD_ALIGNMENT
);
1714 pkt
.ptype
= DCERPC_PKT_REQUEST
;
1715 pkt
.call_id
= req
->call_id
;
1716 pkt
.auth_length
= 0;
1718 pkt
.u
.request
.context_id
= p
->context_id
;
1719 pkt
.u
.request
.opnum
= req
->opnum
;
1722 pkt
.u
.request
.object
.object
= *req
->object
;
1723 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_OBJECT_UUID
;
1724 chunk_size
-= ndr_size_GUID(req
->object
,0);
1727 /* we send a series of pdus without waiting for a reply */
1728 while (remaining
> 0 || first_packet
) {
1729 uint32_t chunk
= MIN(chunk_size
, remaining
);
1730 bool last_frag
= false;
1731 bool do_trans
= false;
1733 first_packet
= false;
1734 pkt
.pfc_flags
&= ~(DCERPC_PFC_FLAG_FIRST
|DCERPC_PFC_FLAG_LAST
);
1736 if (remaining
== stub_data
->length
) {
1737 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_FIRST
;
1739 if (chunk
== remaining
) {
1740 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_LAST
;
1744 pkt
.u
.request
.alloc_hint
= remaining
;
1745 pkt
.u
.request
.stub_and_verifier
.data
= stub_data
->data
+
1746 (stub_data
->length
- remaining
);
1747 pkt
.u
.request
.stub_and_verifier
.length
= chunk
;
1749 req
->status
= ncacn_push_request_sign(p
->conn
, &blob
, req
, sig_size
, &pkt
);
1750 if (!NT_STATUS_IS_OK(req
->status
)) {
1751 req
->state
= RPC_REQUEST_DONE
;
1752 DLIST_REMOVE(p
->conn
->pending
, req
);
1756 if (last_frag
&& !need_async
) {
1760 req
->status
= dcerpc_send_request(p
->conn
, &blob
, do_trans
);
1761 if (!NT_STATUS_IS_OK(req
->status
)) {
1762 req
->state
= RPC_REQUEST_DONE
;
1763 DLIST_REMOVE(p
->conn
->pending
, req
);
1767 if (last_frag
&& !do_trans
) {
1768 req
->status
= dcerpc_send_read(p
->conn
);
1769 if (!NT_STATUS_IS_OK(req
->status
)) {
1770 req
->state
= RPC_REQUEST_DONE
;
1771 DLIST_REMOVE(p
->conn
->pending
, req
);
1780 static void dcerpc_io_trigger(struct tevent_context
*ctx
,
1781 struct tevent_immediate
*im
,
1784 struct dcecli_connection
*c
=
1785 talloc_get_type_abort(private_data
,
1786 struct dcecli_connection
);
1788 c
->io_trigger_pending
= false;
1790 dcerpc_schedule_io_trigger(c
);
1792 dcerpc_ship_next_request(c
);
1795 static void dcerpc_schedule_io_trigger(struct dcecli_connection
*c
)
1801 if (c
->request_queue
== NULL
) {
1805 if (c
->request_queue
->wait_for_sync
&& c
->pending
) {
1809 if (c
->io_trigger_pending
) {
1813 c
->io_trigger_pending
= true;
1815 tevent_schedule_immediate(c
->io_trigger
,
1822 perform the receive side of a async dcerpc request
1824 static NTSTATUS
dcerpc_request_recv(struct rpc_request
*req
,
1825 TALLOC_CTX
*mem_ctx
,
1826 DATA_BLOB
*stub_data
)
1830 while (req
->state
!= RPC_REQUEST_DONE
) {
1831 struct tevent_context
*ctx
= req
->p
->conn
->event_ctx
;
1832 if (tevent_loop_once(ctx
) != 0) {
1833 return NT_STATUS_CONNECTION_DISCONNECTED
;
1836 *stub_data
= req
->payload
;
1837 status
= req
->status
;
1838 if (stub_data
->data
) {
1839 stub_data
->data
= talloc_steal(mem_ctx
, stub_data
->data
);
1841 if (NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
1842 req
->p
->last_fault_code
= req
->fault_code
;
1844 talloc_unlink(talloc_parent(req
), req
);
1849 this is a paranoid NDR validator. For every packet we push onto the wire
1850 we pull it back again, then push it again. Then we compare the raw NDR data
1851 for that to the NDR we initially generated. If they don't match then we know
1852 we must have a bug in either the pull or push side of our code
1854 static NTSTATUS
dcerpc_ndr_validate_in(struct dcecli_connection
*c
,
1855 TALLOC_CTX
*mem_ctx
,
1858 ndr_push_flags_fn_t ndr_push
,
1859 ndr_pull_flags_fn_t ndr_pull
)
1862 struct ndr_pull
*pull
;
1863 struct ndr_push
*push
;
1865 enum ndr_err_code ndr_err
;
1867 st
= talloc_size(mem_ctx
, struct_size
);
1869 return NT_STATUS_NO_MEMORY
;
1872 pull
= ndr_pull_init_flags(c
, &blob
, mem_ctx
);
1874 return NT_STATUS_NO_MEMORY
;
1876 pull
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
1878 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
1879 pull
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
1882 if (c
->flags
& DCERPC_NDR64
) {
1883 pull
->flags
|= LIBNDR_FLAG_NDR64
;
1886 ndr_err
= ndr_pull(pull
, NDR_IN
, st
);
1887 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1888 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1889 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
1890 "failed input validation pull - %s",
1892 return ndr_map_error2ntstatus(ndr_err
);
1895 push
= ndr_push_init_ctx(mem_ctx
);
1897 return NT_STATUS_NO_MEMORY
;
1900 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
1901 push
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
1904 if (c
->flags
& DCERPC_NDR64
) {
1905 push
->flags
|= LIBNDR_FLAG_NDR64
;
1908 ndr_err
= ndr_push(push
, NDR_IN
, st
);
1909 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1910 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1911 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
1912 "failed input validation push - %s",
1914 return ndr_map_error2ntstatus(ndr_err
);
1917 blob2
= ndr_push_blob(push
);
1919 if (data_blob_cmp(&blob
, &blob2
) != 0) {
1920 DEBUG(3,("original:\n"));
1921 dump_data(3, blob
.data
, blob
.length
);
1922 DEBUG(3,("secondary:\n"));
1923 dump_data(3, blob2
.data
, blob2
.length
);
1924 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
1925 "failed input validation blobs doesn't match");
1926 return ndr_map_error2ntstatus(ndr_err
);
1929 return NT_STATUS_OK
;
1933 this is a paranoid NDR input validator. For every packet we pull
1934 from the wire we push it back again then pull and push it
1935 again. Then we compare the raw NDR data for that to the NDR we
1936 initially generated. If they don't match then we know we must have a
1937 bug in either the pull or push side of our code
1939 static NTSTATUS
dcerpc_ndr_validate_out(struct dcecli_connection
*c
,
1940 struct ndr_pull
*pull_in
,
1943 ndr_push_flags_fn_t ndr_push
,
1944 ndr_pull_flags_fn_t ndr_pull
,
1945 ndr_print_function_t ndr_print
)
1948 struct ndr_pull
*pull
;
1949 struct ndr_push
*push
;
1950 DATA_BLOB blob
, blob2
;
1951 TALLOC_CTX
*mem_ctx
= pull_in
;
1953 enum ndr_err_code ndr_err
;
1955 st
= talloc_size(mem_ctx
, struct_size
);
1957 return NT_STATUS_NO_MEMORY
;
1959 memcpy(st
, struct_ptr
, struct_size
);
1961 push
= ndr_push_init_ctx(mem_ctx
);
1963 return NT_STATUS_NO_MEMORY
;
1966 ndr_err
= ndr_push(push
, NDR_OUT
, struct_ptr
);
1967 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1968 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1969 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
1970 "failed output validation push - %s",
1972 return ndr_map_error2ntstatus(ndr_err
);
1975 blob
= ndr_push_blob(push
);
1977 pull
= ndr_pull_init_flags(c
, &blob
, mem_ctx
);
1979 return NT_STATUS_NO_MEMORY
;
1982 pull
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
1983 ndr_err
= ndr_pull(pull
, NDR_OUT
, st
);
1984 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1985 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1986 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
1987 "failed output validation pull - %s",
1989 return ndr_map_error2ntstatus(ndr_err
);
1992 push
= ndr_push_init_ctx(mem_ctx
);
1994 return NT_STATUS_NO_MEMORY
;
1997 ndr_err
= ndr_push(push
, NDR_OUT
, st
);
1998 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1999 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
2000 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
2001 "failed output validation push2 - %s",
2003 return ndr_map_error2ntstatus(ndr_err
);
2006 blob2
= ndr_push_blob(push
);
2008 if (data_blob_cmp(&blob
, &blob2
) != 0) {
2009 DEBUG(3,("original:\n"));
2010 dump_data(3, blob
.data
, blob
.length
);
2011 DEBUG(3,("secondary:\n"));
2012 dump_data(3, blob2
.data
, blob2
.length
);
2013 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
2014 "failed output validation blobs doesn't match");
2015 return ndr_map_error2ntstatus(ndr_err
);
2018 /* this checks the printed forms of the two structures, which effectively
2019 tests all of the value() attributes */
2020 s1
= ndr_print_function_string(mem_ctx
, ndr_print
, "VALIDATE",
2021 NDR_OUT
, struct_ptr
);
2022 s2
= ndr_print_function_string(mem_ctx
, ndr_print
, "VALIDATE",
2024 if (strcmp(s1
, s2
) != 0) {
2026 DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1
, s2
));
2028 /* this is sometimes useful */
2029 printf("VALIDATE ERROR\n");
2030 file_save("wire.dat", s1
, strlen(s1
));
2031 file_save("gen.dat", s2
, strlen(s2
));
2032 system("diff -u wire.dat gen.dat");
2034 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
2035 "failed output validation strings doesn't match");
2036 return ndr_map_error2ntstatus(ndr_err
);
2039 return NT_STATUS_OK
;
2043 a useful function for retrieving the server name we connected to
2045 _PUBLIC_
const char *dcerpc_server_name(struct dcerpc_pipe
*p
)
2047 return p
->conn
? p
->conn
->server_name
: NULL
;
2052 get the dcerpc auth_level for a open connection
2054 uint32_t dcerpc_auth_level(struct dcecli_connection
*c
)
2058 if (c
->flags
& DCERPC_SEAL
) {
2059 auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
2060 } else if (c
->flags
& DCERPC_SIGN
) {
2061 auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
2062 } else if (c
->flags
& DCERPC_PACKET
) {
2063 auth_level
= DCERPC_AUTH_LEVEL_PACKET
;
2064 } else if (c
->flags
& DCERPC_CONNECT
) {
2065 auth_level
= DCERPC_AUTH_LEVEL_CONNECT
;
2067 auth_level
= DCERPC_AUTH_LEVEL_NONE
;
2072 struct dcerpc_alter_context_state
{
2073 struct tevent_context
*ev
;
2074 struct dcerpc_pipe
*p
;
2077 static void dcerpc_alter_context_fail_handler(struct rpc_request
*subreq
);
2078 static void dcerpc_alter_context_recv_handler(struct rpc_request
*req
,
2079 DATA_BLOB
*raw_packet
,
2080 struct ncacn_packet
*pkt
);
2082 struct tevent_req
*dcerpc_alter_context_send(TALLOC_CTX
*mem_ctx
,
2083 struct tevent_context
*ev
,
2084 struct dcerpc_pipe
*p
,
2085 const struct ndr_syntax_id
*syntax
,
2086 const struct ndr_syntax_id
*transfer_syntax
)
2088 struct tevent_req
*req
;
2089 struct dcerpc_alter_context_state
*state
;
2090 struct ncacn_packet pkt
;
2093 struct rpc_request
*subreq
;
2096 req
= tevent_req_create(mem_ctx
, &state
,
2097 struct dcerpc_alter_context_state
);
2105 p
->syntax
= *syntax
;
2106 p
->transfer_syntax
= *transfer_syntax
;
2108 flags
= dcerpc_binding_get_flags(p
->binding
);
2110 init_ncacn_hdr(p
->conn
, &pkt
);
2112 pkt
.ptype
= DCERPC_PKT_ALTER
;
2113 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
2114 pkt
.call_id
= p
->conn
->call_id
;
2115 pkt
.auth_length
= 0;
2117 if (flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
2118 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
2121 pkt
.u
.alter
.max_xmit_frag
= p
->conn
->srv_max_xmit_frag
;
2122 pkt
.u
.alter
.max_recv_frag
= p
->conn
->srv_max_recv_frag
;
2123 pkt
.u
.alter
.assoc_group_id
= dcerpc_binding_get_assoc_group_id(p
->binding
);
2124 pkt
.u
.alter
.num_contexts
= 1;
2125 pkt
.u
.alter
.ctx_list
= talloc_zero_array(state
, struct dcerpc_ctx_list
,
2126 pkt
.u
.alter
.num_contexts
);
2127 if (tevent_req_nomem(pkt
.u
.alter
.ctx_list
, req
)) {
2128 return tevent_req_post(req
, ev
);
2130 pkt
.u
.alter
.ctx_list
[0].context_id
= p
->context_id
;
2131 pkt
.u
.alter
.ctx_list
[0].num_transfer_syntaxes
= 1;
2132 pkt
.u
.alter
.ctx_list
[0].abstract_syntax
= p
->syntax
;
2133 pkt
.u
.alter
.ctx_list
[0].transfer_syntaxes
= &p
->transfer_syntax
;
2134 pkt
.u
.alter
.auth_info
= data_blob(NULL
, 0);
2136 /* construct the NDR form of the packet */
2137 status
= dcerpc_ncacn_push_auth(&blob
,
2140 p
->conn
->security_state
.tmp_auth_info
.out
);
2141 if (tevent_req_nterror(req
, status
)) {
2142 return tevent_req_post(req
, ev
);
2146 * we allocate a dcerpc_request so we can be in the same
2147 * request queue as normal requests
2149 subreq
= talloc_zero(state
, struct rpc_request
);
2150 if (tevent_req_nomem(subreq
, req
)) {
2151 return tevent_req_post(req
, ev
);
2154 subreq
->state
= RPC_REQUEST_PENDING
;
2155 subreq
->call_id
= pkt
.call_id
;
2156 subreq
->async
.private_data
= req
;
2157 subreq
->async
.callback
= dcerpc_alter_context_fail_handler
;
2159 subreq
->recv_handler
= dcerpc_alter_context_recv_handler
;
2160 DLIST_ADD_END(p
->conn
->pending
, subreq
);
2161 talloc_set_destructor(subreq
, dcerpc_req_dequeue
);
2163 status
= dcerpc_send_request(p
->conn
, &blob
, true);
2164 if (tevent_req_nterror(req
, status
)) {
2165 return tevent_req_post(req
, ev
);
2168 tevent_add_timer(ev
, subreq
,
2169 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT
, 0),
2170 dcerpc_timeout_handler
, subreq
);
2175 static void dcerpc_alter_context_fail_handler(struct rpc_request
*subreq
)
2177 struct tevent_req
*req
=
2178 talloc_get_type_abort(subreq
->async
.private_data
,
2180 struct dcerpc_alter_context_state
*state
=
2181 tevent_req_data(req
,
2182 struct dcerpc_alter_context_state
);
2183 NTSTATUS status
= subreq
->status
;
2185 TALLOC_FREE(subreq
);
2188 * We trigger the callback in the next event run
2189 * because the code in this file might trigger
2190 * multiple request callbacks from within a single
2193 * In order to avoid segfaults from within
2194 * dcerpc_connection_dead() we call
2195 * tevent_req_defer_callback().
2197 tevent_req_defer_callback(req
, state
->ev
);
2199 tevent_req_nterror(req
, status
);
2202 static void dcerpc_alter_context_recv_handler(struct rpc_request
*subreq
,
2203 DATA_BLOB
*raw_packet
,
2204 struct ncacn_packet
*pkt
)
2206 struct tevent_req
*req
=
2207 talloc_get_type_abort(subreq
->async
.private_data
,
2209 struct dcerpc_alter_context_state
*state
=
2210 tevent_req_data(req
,
2211 struct dcerpc_alter_context_state
);
2212 struct dcecli_connection
*conn
= state
->p
->conn
;
2213 struct dcecli_security
*sec
= &conn
->security_state
;
2217 * Note that pkt is allocated under raw_packet->data,
2218 * while raw_packet->data is a child of subreq.
2220 talloc_steal(state
, raw_packet
->data
);
2221 TALLOC_FREE(subreq
);
2224 * We trigger the callback in the next event run
2225 * because the code in this file might trigger
2226 * multiple request callbacks from within a single
2229 * In order to avoid segfaults from within
2230 * dcerpc_connection_dead() we call
2231 * tevent_req_defer_callback().
2233 tevent_req_defer_callback(req
, state
->ev
);
2235 if (pkt
->ptype
== DCERPC_PKT_FAULT
) {
2236 DEBUG(5,("dcerpc: alter_resp - rpc fault: %s\n",
2237 dcerpc_errstr(state
, pkt
->u
.fault
.status
)));
2238 if (pkt
->u
.fault
.status
== DCERPC_FAULT_ACCESS_DENIED
) {
2239 state
->p
->last_fault_code
= pkt
->u
.fault
.status
;
2240 tevent_req_nterror(req
, NT_STATUS_LOGON_FAILURE
);
2241 } else if (pkt
->u
.fault
.status
== DCERPC_FAULT_SEC_PKG_ERROR
) {
2242 state
->p
->last_fault_code
= pkt
->u
.fault
.status
;
2243 tevent_req_nterror(req
, NT_STATUS_LOGON_FAILURE
);
2245 state
->p
->last_fault_code
= pkt
->u
.fault
.status
;
2246 status
= dcerpc_fault_to_nt_status(pkt
->u
.fault
.status
);
2247 tevent_req_nterror(req
, status
);
2252 status
= dcerpc_verify_ncacn_packet_header(pkt
,
2253 DCERPC_PKT_ALTER_RESP
,
2254 pkt
->u
.alter_resp
.auth_info
.length
,
2255 DCERPC_PFC_FLAG_FIRST
|
2256 DCERPC_PFC_FLAG_LAST
,
2257 DCERPC_PFC_FLAG_CONC_MPX
|
2258 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
);
2259 if (!NT_STATUS_IS_OK(status
)) {
2260 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
2261 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
2265 if (pkt
->u
.alter_resp
.num_results
!= 1) {
2266 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
2267 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
2271 if (pkt
->u
.alter_resp
.ctx_list
[0].result
!= 0) {
2272 status
= dcerpc_map_ack_reason(&pkt
->u
.alter_resp
.ctx_list
[0]);
2273 DEBUG(2,("dcerpc: alter_resp failed - reason %d - %s\n",
2274 pkt
->u
.alter_resp
.ctx_list
[0].reason
.value
,
2275 nt_errstr(status
)));
2276 tevent_req_nterror(req
, status
);
2280 /* the alter_resp might contain a reply set of credentials */
2281 if (pkt
->auth_length
!= 0 && sec
->tmp_auth_info
.in
!= NULL
) {
2282 status
= dcerpc_pull_auth_trailer(pkt
, sec
->tmp_auth_info
.mem
,
2283 &pkt
->u
.alter_resp
.auth_info
,
2284 sec
->tmp_auth_info
.in
,
2286 if (tevent_req_nterror(req
, status
)) {
2291 tevent_req_done(req
);
2294 NTSTATUS
dcerpc_alter_context_recv(struct tevent_req
*req
)
2296 return tevent_req_simple_recv_ntstatus(req
);
2300 send a dcerpc alter_context request
2302 _PUBLIC_ NTSTATUS
dcerpc_alter_context(struct dcerpc_pipe
*p
,
2303 TALLOC_CTX
*mem_ctx
,
2304 const struct ndr_syntax_id
*syntax
,
2305 const struct ndr_syntax_id
*transfer_syntax
)
2307 struct tevent_req
*subreq
;
2308 struct tevent_context
*ev
= p
->conn
->event_ctx
;
2311 /* TODO: create a new event context here */
2313 subreq
= dcerpc_alter_context_send(mem_ctx
, ev
,
2314 p
, syntax
, transfer_syntax
);
2315 if (subreq
== NULL
) {
2316 return NT_STATUS_NO_MEMORY
;
2319 ok
= tevent_req_poll(subreq
, ev
);
2322 status
= map_nt_error_from_unix_common(errno
);
2326 return dcerpc_alter_context_recv(subreq
);
2329 static void dcerpc_transport_dead(struct dcecli_connection
*c
, NTSTATUS status
)
2331 if (c
->transport
.stream
== NULL
) {
2335 tevent_queue_stop(c
->transport
.write_queue
);
2336 TALLOC_FREE(c
->transport
.read_subreq
);
2337 TALLOC_FREE(c
->transport
.stream
);
2339 if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL
, status
)) {
2340 status
= NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
2343 if (NT_STATUS_EQUAL(NT_STATUS_OK
, status
)) {
2344 status
= NT_STATUS_END_OF_FILE
;
2347 dcerpc_recv_data(c
, NULL
, status
);
2352 shutdown SMB pipe connection
2354 struct dcerpc_shutdown_pipe_state
{
2355 struct dcecli_connection
*c
;
2359 static void dcerpc_shutdown_pipe_done(struct tevent_req
*subreq
);
2361 static NTSTATUS
dcerpc_shutdown_pipe(struct dcecli_connection
*c
, NTSTATUS status
)
2363 struct dcerpc_shutdown_pipe_state
*state
;
2364 struct tevent_req
*subreq
;
2366 if (c
->transport
.stream
== NULL
) {
2367 return NT_STATUS_OK
;
2370 state
= talloc_zero(c
, struct dcerpc_shutdown_pipe_state
);
2371 if (state
== NULL
) {
2372 return NT_STATUS_NO_MEMORY
;
2375 state
->status
= status
;
2377 subreq
= tstream_disconnect_send(state
, c
->event_ctx
, c
->transport
.stream
);
2378 if (subreq
== NULL
) {
2379 return NT_STATUS_NO_MEMORY
;
2381 tevent_req_set_callback(subreq
, dcerpc_shutdown_pipe_done
, state
);
2386 static void dcerpc_shutdown_pipe_done(struct tevent_req
*subreq
)
2388 struct dcerpc_shutdown_pipe_state
*state
=
2389 tevent_req_callback_data(subreq
, struct dcerpc_shutdown_pipe_state
);
2390 struct dcecli_connection
*c
= state
->c
;
2391 NTSTATUS status
= state
->status
;
2395 * here we ignore the return values...
2397 tstream_disconnect_recv(subreq
, &error
);
2398 TALLOC_FREE(subreq
);
2402 dcerpc_transport_dead(c
, status
);
2407 struct dcerpc_send_read_state
{
2408 struct dcecli_connection
*p
;
2411 static int dcerpc_send_read_state_destructor(struct dcerpc_send_read_state
*state
)
2413 struct dcecli_connection
*p
= state
->p
;
2415 p
->transport
.read_subreq
= NULL
;
2420 static void dcerpc_send_read_done(struct tevent_req
*subreq
);
2422 static NTSTATUS
dcerpc_send_read(struct dcecli_connection
*p
)
2424 struct dcerpc_send_read_state
*state
;
2426 if (p
->transport
.read_subreq
!= NULL
) {
2427 p
->transport
.pending_reads
++;
2428 return NT_STATUS_OK
;
2431 state
= talloc_zero(p
, struct dcerpc_send_read_state
);
2432 if (state
== NULL
) {
2433 return NT_STATUS_NO_MEMORY
;
2437 talloc_set_destructor(state
, dcerpc_send_read_state_destructor
);
2439 p
->transport
.read_subreq
= dcerpc_read_ncacn_packet_send(state
,
2441 p
->transport
.stream
);
2442 if (p
->transport
.read_subreq
== NULL
) {
2443 return NT_STATUS_NO_MEMORY
;
2445 tevent_req_set_callback(p
->transport
.read_subreq
, dcerpc_send_read_done
, state
);
2447 return NT_STATUS_OK
;
2450 static void dcerpc_send_read_done(struct tevent_req
*subreq
)
2452 struct dcerpc_send_read_state
*state
=
2453 tevent_req_callback_data(subreq
,
2454 struct dcerpc_send_read_state
);
2455 struct dcecli_connection
*p
= state
->p
;
2457 struct ncacn_packet
*pkt
;
2460 status
= dcerpc_read_ncacn_packet_recv(subreq
, state
,
2462 TALLOC_FREE(subreq
);
2463 if (!NT_STATUS_IS_OK(status
)) {
2465 dcerpc_transport_dead(p
, status
);
2470 * here we steal into thet connection context,
2471 * but p->transport.recv_data() will steal or free it again
2473 talloc_steal(p
, blob
.data
);
2476 if (p
->transport
.pending_reads
> 0) {
2477 p
->transport
.pending_reads
--;
2479 status
= dcerpc_send_read(p
);
2480 if (!NT_STATUS_IS_OK(status
)) {
2481 dcerpc_transport_dead(p
, status
);
2486 dcerpc_recv_data(p
, &blob
, NT_STATUS_OK
);
2489 struct dcerpc_send_request_state
{
2490 struct dcecli_connection
*p
;
2495 static int dcerpc_send_request_state_destructor(struct dcerpc_send_request_state
*state
)
2497 struct dcecli_connection
*p
= state
->p
;
2499 p
->transport
.read_subreq
= NULL
;
2504 static void dcerpc_send_request_wait_done(struct tevent_req
*subreq
);
2505 static void dcerpc_send_request_done(struct tevent_req
*subreq
);
2507 static NTSTATUS
dcerpc_send_request(struct dcecli_connection
*p
, DATA_BLOB
*data
,
2510 struct dcerpc_send_request_state
*state
;
2511 struct tevent_req
*subreq
;
2512 bool use_trans
= trigger_read
;
2514 if (p
->transport
.stream
== NULL
) {
2515 return NT_STATUS_CONNECTION_DISCONNECTED
;
2518 state
= talloc_zero(p
, struct dcerpc_send_request_state
);
2519 if (state
== NULL
) {
2520 return NT_STATUS_NO_MEMORY
;
2524 state
->blob
= data_blob_talloc(state
, data
->data
, data
->length
);
2525 if (state
->blob
.data
== NULL
) {
2527 return NT_STATUS_NO_MEMORY
;
2529 state
->iov
.iov_base
= (void *)state
->blob
.data
;
2530 state
->iov
.iov_len
= state
->blob
.length
;
2532 if (p
->transport
.read_subreq
!= NULL
) {
2536 if (!tstream_is_smbXcli_np(p
->transport
.stream
)) {
2542 * we need to block reads until our write is
2543 * the next in the write queue.
2545 p
->transport
.read_subreq
= tevent_queue_wait_send(state
, p
->event_ctx
,
2546 p
->transport
.write_queue
);
2547 if (p
->transport
.read_subreq
== NULL
) {
2549 return NT_STATUS_NO_MEMORY
;
2551 tevent_req_set_callback(p
->transport
.read_subreq
,
2552 dcerpc_send_request_wait_done
,
2555 talloc_set_destructor(state
, dcerpc_send_request_state_destructor
);
2557 trigger_read
= false;
2560 subreq
= tstream_writev_queue_send(state
, p
->event_ctx
,
2561 p
->transport
.stream
,
2562 p
->transport
.write_queue
,
2564 if (subreq
== NULL
) {
2566 return NT_STATUS_NO_MEMORY
;
2568 tevent_req_set_callback(subreq
, dcerpc_send_request_done
, state
);
2571 dcerpc_send_read(p
);
2574 return NT_STATUS_OK
;
2577 static void dcerpc_send_request_wait_done(struct tevent_req
*subreq
)
2579 struct dcerpc_send_request_state
*state
=
2580 tevent_req_callback_data(subreq
,
2581 struct dcerpc_send_request_state
);
2582 struct dcecli_connection
*p
= state
->p
;
2586 p
->transport
.read_subreq
= NULL
;
2587 talloc_set_destructor(state
, NULL
);
2589 ok
= tevent_queue_wait_recv(subreq
);
2592 dcerpc_transport_dead(p
, NT_STATUS_NO_MEMORY
);
2596 if (tevent_queue_length(p
->transport
.write_queue
) <= 2) {
2597 status
= tstream_smbXcli_np_use_trans(p
->transport
.stream
);
2598 if (!NT_STATUS_IS_OK(status
)) {
2600 dcerpc_transport_dead(p
, status
);
2605 /* we free subreq after tstream_cli_np_use_trans */
2606 TALLOC_FREE(subreq
);
2608 dcerpc_send_read(p
);
2611 static void dcerpc_send_request_done(struct tevent_req
*subreq
)
2613 struct dcerpc_send_request_state
*state
=
2614 tevent_req_callback_data(subreq
,
2615 struct dcerpc_send_request_state
);
2619 ret
= tstream_writev_queue_recv(subreq
, &error
);
2620 TALLOC_FREE(subreq
);
2622 struct dcecli_connection
*p
= state
->p
;
2623 NTSTATUS status
= map_nt_error_from_unix_common(error
);
2626 dcerpc_transport_dead(p
, status
);