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 "auth/gensec/gensec.h"
31 #include "param/param.h"
32 #include "lib/util/tevent_ntstatus.h"
33 #include "librpc/rpc/rpc_common.h"
35 enum rpc_request_state
{
42 handle for an async dcerpc request
45 struct rpc_request
*next
, *prev
;
46 struct dcerpc_pipe
*p
;
49 enum rpc_request_state state
;
54 /* this is used to distinguish bind and alter_context requests
55 from normal requests */
56 void (*recv_handler
)(struct rpc_request
*conn
,
57 DATA_BLOB
*blob
, struct ncacn_packet
*pkt
);
59 const struct GUID
*object
;
61 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_schedule_io_trigger(struct dcecli_connection
*c
);
87 static struct rpc_request
*dcerpc_request_send(TALLOC_CTX
*mem_ctx
,
88 struct dcerpc_pipe
*p
,
89 const struct GUID
*object
,
91 DATA_BLOB
*stub_data
);
92 static NTSTATUS
dcerpc_request_recv(struct rpc_request
*req
,
94 DATA_BLOB
*stub_data
);
95 static NTSTATUS
dcerpc_ndr_validate_in(struct dcecli_connection
*c
,
99 ndr_push_flags_fn_t ndr_push
,
100 ndr_pull_flags_fn_t ndr_pull
);
101 static NTSTATUS
dcerpc_ndr_validate_out(struct dcecli_connection
*c
,
102 struct ndr_pull
*pull_in
,
105 ndr_push_flags_fn_t ndr_push
,
106 ndr_pull_flags_fn_t ndr_pull
,
107 ndr_print_function_t ndr_print
);
109 /* destroy a dcerpc connection */
110 static int dcerpc_connection_destructor(struct dcecli_connection
*conn
)
113 conn
->free_skipped
= true;
116 dcerpc_connection_dead(conn
, NT_STATUS_LOCAL_DISCONNECT
);
121 /* initialise a dcerpc connection.
122 the event context is optional
124 static struct dcecli_connection
*dcerpc_connection_init(TALLOC_CTX
*mem_ctx
,
125 struct tevent_context
*ev
)
127 struct dcecli_connection
*c
;
129 c
= talloc_zero(mem_ctx
, struct dcecli_connection
);
136 if (c
->event_ctx
== NULL
) {
142 c
->security_state
.auth_info
= NULL
;
143 c
->security_state
.session_key
= dcerpc_generic_session_key
;
144 c
->security_state
.generic_state
= NULL
;
145 c
->binding_string
= NULL
;
147 c
->srv_max_xmit_frag
= 0;
148 c
->srv_max_recv_frag
= 0;
151 c
->io_trigger
= tevent_create_immediate(c
);
152 if (c
->io_trigger
== NULL
) {
157 talloc_set_destructor(c
, dcerpc_connection_destructor
);
162 struct dcerpc_bh_state
{
163 struct dcerpc_pipe
*p
;
166 static bool dcerpc_bh_is_connected(struct dcerpc_binding_handle
*h
)
168 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
169 struct dcerpc_bh_state
);
179 if (hs
->p
->conn
->dead
) {
186 static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle
*h
,
189 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
190 struct dcerpc_bh_state
);
194 return DCERPC_REQUEST_TIMEOUT
;
197 old
= hs
->p
->request_timeout
;
198 hs
->p
->request_timeout
= timeout
;
203 static void dcerpc_bh_auth_info(struct dcerpc_binding_handle
*h
,
204 enum dcerpc_AuthType
*auth_type
,
205 enum dcerpc_AuthLevel
*auth_level
)
207 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
208 struct dcerpc_bh_state
);
214 if (hs
->p
->conn
== NULL
) {
218 if (hs
->p
->conn
->security_state
.auth_info
== NULL
) {
222 *auth_type
= hs
->p
->conn
->security_state
.auth_info
->auth_type
;
223 *auth_level
= hs
->p
->conn
->security_state
.auth_info
->auth_level
;
226 struct dcerpc_bh_raw_call_state
{
227 struct tevent_context
*ev
;
228 struct dcerpc_binding_handle
*h
;
234 static void dcerpc_bh_raw_call_done(struct rpc_request
*subreq
);
236 static struct tevent_req
*dcerpc_bh_raw_call_send(TALLOC_CTX
*mem_ctx
,
237 struct tevent_context
*ev
,
238 struct dcerpc_binding_handle
*h
,
239 const struct GUID
*object
,
242 const uint8_t *in_data
,
245 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
246 struct dcerpc_bh_state
);
247 struct tevent_req
*req
;
248 struct dcerpc_bh_raw_call_state
*state
;
250 struct rpc_request
*subreq
;
252 req
= tevent_req_create(mem_ctx
, &state
,
253 struct dcerpc_bh_raw_call_state
);
259 state
->in_data
.data
= discard_const_p(uint8_t, in_data
);
260 state
->in_data
.length
= in_length
;
262 ok
= dcerpc_bh_is_connected(h
);
264 tevent_req_nterror(req
, NT_STATUS_CONNECTION_DISCONNECTED
);
265 return tevent_req_post(req
, ev
);
268 subreq
= dcerpc_request_send(state
,
273 if (tevent_req_nomem(subreq
, req
)) {
274 return tevent_req_post(req
, ev
);
276 subreq
->async
.callback
= dcerpc_bh_raw_call_done
;
277 subreq
->async
.private_data
= req
;
282 static void dcerpc_bh_raw_call_done(struct rpc_request
*subreq
)
284 struct tevent_req
*req
=
285 talloc_get_type_abort(subreq
->async
.private_data
,
287 struct dcerpc_bh_raw_call_state
*state
=
289 struct dcerpc_bh_raw_call_state
);
293 state
->out_flags
= 0;
294 if (subreq
->flags
& DCERPC_PULL_BIGENDIAN
) {
295 state
->out_flags
|= LIBNDR_FLAG_BIGENDIAN
;
298 fault_code
= subreq
->fault_code
;
300 status
= dcerpc_request_recv(subreq
, state
, &state
->out_data
);
301 if (NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
302 status
= dcerpc_fault_to_nt_status(fault_code
);
306 * We trigger the callback in the next event run
307 * because the code in this file might trigger
308 * multiple request callbacks from within a single
311 * In order to avoid segfaults from within
312 * dcerpc_connection_dead() we call
313 * tevent_req_defer_callback().
315 tevent_req_defer_callback(req
, state
->ev
);
317 if (!NT_STATUS_IS_OK(status
)) {
318 tevent_req_nterror(req
, status
);
322 tevent_req_done(req
);
325 static NTSTATUS
dcerpc_bh_raw_call_recv(struct tevent_req
*req
,
331 struct dcerpc_bh_raw_call_state
*state
=
333 struct dcerpc_bh_raw_call_state
);
336 if (tevent_req_is_nterror(req
, &status
)) {
337 tevent_req_received(req
);
341 *out_data
= talloc_move(mem_ctx
, &state
->out_data
.data
);
342 *out_length
= state
->out_data
.length
;
343 *out_flags
= state
->out_flags
;
344 tevent_req_received(req
);
348 struct dcerpc_bh_disconnect_state
{
352 static struct tevent_req
*dcerpc_bh_disconnect_send(TALLOC_CTX
*mem_ctx
,
353 struct tevent_context
*ev
,
354 struct dcerpc_binding_handle
*h
)
356 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
357 struct dcerpc_bh_state
);
358 struct tevent_req
*req
;
359 struct dcerpc_bh_disconnect_state
*state
;
362 req
= tevent_req_create(mem_ctx
, &state
,
363 struct dcerpc_bh_disconnect_state
);
368 ok
= dcerpc_bh_is_connected(h
);
370 tevent_req_nterror(req
, NT_STATUS_CONNECTION_DISCONNECTED
);
371 return tevent_req_post(req
, ev
);
374 /* TODO: do a real disconnect ... */
377 tevent_req_done(req
);
378 return tevent_req_post(req
, ev
);
381 static NTSTATUS
dcerpc_bh_disconnect_recv(struct tevent_req
*req
)
385 if (tevent_req_is_nterror(req
, &status
)) {
386 tevent_req_received(req
);
390 tevent_req_received(req
);
394 static bool dcerpc_bh_push_bigendian(struct dcerpc_binding_handle
*h
)
396 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
397 struct dcerpc_bh_state
);
399 if (hs
->p
->conn
->flags
& DCERPC_PUSH_BIGENDIAN
) {
406 static bool dcerpc_bh_ref_alloc(struct dcerpc_binding_handle
*h
)
408 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
409 struct dcerpc_bh_state
);
411 if (hs
->p
->conn
->flags
& DCERPC_NDR_REF_ALLOC
) {
418 static bool dcerpc_bh_use_ndr64(struct dcerpc_binding_handle
*h
)
420 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
421 struct dcerpc_bh_state
);
423 if (hs
->p
->conn
->flags
& DCERPC_NDR64
) {
430 static void dcerpc_bh_do_ndr_print(struct dcerpc_binding_handle
*h
,
432 const void *_struct_ptr
,
433 const struct ndr_interface_call
*call
)
435 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
436 struct dcerpc_bh_state
);
437 void *struct_ptr
= discard_const(_struct_ptr
);
439 if (ndr_flags
& NDR_IN
) {
440 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_PRINT_IN
) {
441 ndr_print_function_debug(call
->ndr_print
,
447 if (ndr_flags
& NDR_OUT
) {
448 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_PRINT_OUT
) {
449 ndr_print_function_debug(call
->ndr_print
,
457 static void dcerpc_bh_ndr_push_failed(struct dcerpc_binding_handle
*h
,
459 const void *struct_ptr
,
460 const struct ndr_interface_call
*call
)
462 DEBUG(2,("Unable to ndr_push structure for %s - %s\n",
463 call
->name
, nt_errstr(error
)));
466 static void dcerpc_bh_ndr_pull_failed(struct dcerpc_binding_handle
*h
,
468 const DATA_BLOB
*blob
,
469 const struct ndr_interface_call
*call
)
471 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
472 struct dcerpc_bh_state
);
473 const uint32_t num_examples
= 20;
476 DEBUG(2,("Unable to ndr_pull structure for %s - %s\n",
477 call
->name
, nt_errstr(error
)));
479 if (hs
->p
->conn
->packet_log_dir
== NULL
) return;
481 for (i
=0;i
<num_examples
;i
++) {
483 asprintf(&name
, "%s/rpclog/%s-out.%d",
484 hs
->p
->conn
->packet_log_dir
,
489 if (!file_exist(name
)) {
490 if (file_save(name
, blob
->data
, blob
->length
)) {
491 DEBUG(10,("Logged rpc packet to %s\n", name
));
500 static NTSTATUS
dcerpc_bh_ndr_validate_in(struct dcerpc_binding_handle
*h
,
502 const DATA_BLOB
*blob
,
503 const struct ndr_interface_call
*call
)
505 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
506 struct dcerpc_bh_state
);
508 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_VALIDATE_IN
) {
511 status
= dcerpc_ndr_validate_in(hs
->p
->conn
,
517 if (!NT_STATUS_IS_OK(status
)) {
518 DEBUG(0,("Validation [in] failed for %s - %s\n",
519 call
->name
, nt_errstr(status
)));
524 DEBUG(10,("rpc request data:\n"));
525 dump_data(10, blob
->data
, blob
->length
);
530 static NTSTATUS
dcerpc_bh_ndr_validate_out(struct dcerpc_binding_handle
*h
,
531 struct ndr_pull
*pull_in
,
532 const void *_struct_ptr
,
533 const struct ndr_interface_call
*call
)
535 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
536 struct dcerpc_bh_state
);
537 void *struct_ptr
= discard_const(_struct_ptr
);
539 DEBUG(10,("rpc reply data:\n"));
540 dump_data(10, pull_in
->data
, pull_in
->data_size
);
542 if (pull_in
->offset
!= pull_in
->data_size
) {
543 DEBUG(0,("Warning! ignoring %u unread bytes at ofs:%u (0x%08X) for %s!\n",
544 pull_in
->data_size
- pull_in
->offset
,
545 pull_in
->offset
, pull_in
->offset
,
547 /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here,
548 but it turns out that early versions of NT
549 (specifically NT3.1) add junk onto the end of rpc
550 packets, so if we want to interoperate at all with
551 those versions then we need to ignore this error */
554 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_VALIDATE_OUT
) {
557 status
= dcerpc_ndr_validate_out(hs
->p
->conn
,
564 if (!NT_STATUS_IS_OK(status
)) {
565 DEBUG(2,("Validation [out] failed for %s - %s\n",
566 call
->name
, nt_errstr(status
)));
574 static const struct dcerpc_binding_handle_ops dcerpc_bh_ops
= {
576 .is_connected
= dcerpc_bh_is_connected
,
577 .set_timeout
= dcerpc_bh_set_timeout
,
578 .auth_info
= dcerpc_bh_auth_info
,
579 .raw_call_send
= dcerpc_bh_raw_call_send
,
580 .raw_call_recv
= dcerpc_bh_raw_call_recv
,
581 .disconnect_send
= dcerpc_bh_disconnect_send
,
582 .disconnect_recv
= dcerpc_bh_disconnect_recv
,
584 .push_bigendian
= dcerpc_bh_push_bigendian
,
585 .ref_alloc
= dcerpc_bh_ref_alloc
,
586 .use_ndr64
= dcerpc_bh_use_ndr64
,
587 .do_ndr_print
= dcerpc_bh_do_ndr_print
,
588 .ndr_push_failed
= dcerpc_bh_ndr_push_failed
,
589 .ndr_pull_failed
= dcerpc_bh_ndr_pull_failed
,
590 .ndr_validate_in
= dcerpc_bh_ndr_validate_in
,
591 .ndr_validate_out
= dcerpc_bh_ndr_validate_out
,
594 /* initialise a dcerpc pipe. */
595 struct dcerpc_binding_handle
*dcerpc_pipe_binding_handle(struct dcerpc_pipe
*p
)
597 struct dcerpc_binding_handle
*h
;
598 struct dcerpc_bh_state
*hs
;
600 h
= dcerpc_binding_handle_create(p
,
605 struct dcerpc_bh_state
,
612 dcerpc_binding_handle_set_sync_ev(h
, p
->conn
->event_ctx
);
617 /* initialise a dcerpc pipe. */
618 _PUBLIC_
struct dcerpc_pipe
*dcerpc_pipe_init(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
)
620 struct dcerpc_pipe
*p
;
622 p
= talloc_zero(mem_ctx
, struct dcerpc_pipe
);
627 p
->conn
= dcerpc_connection_init(p
, ev
);
628 if (p
->conn
== NULL
) {
633 p
->last_fault_code
= 0;
635 p
->request_timeout
= DCERPC_REQUEST_TIMEOUT
;
638 ZERO_STRUCT(p
->syntax
);
639 ZERO_STRUCT(p
->transfer_syntax
);
642 p
->conn
->flags
|= DCERPC_DEBUG_PRINT_BOTH
;
645 p
->binding_handle
= dcerpc_pipe_binding_handle(p
);
646 if (p
->binding_handle
== NULL
) {
656 choose the next call id to use
658 static uint32_t next_call_id(struct dcecli_connection
*c
)
661 if (c
->call_id
== 0) {
668 setup for a ndr pull, also setting up any flags from the binding string
670 static struct ndr_pull
*ndr_pull_init_flags(struct dcecli_connection
*c
,
671 DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
)
673 struct ndr_pull
*ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
675 if (ndr
== NULL
) return ndr
;
677 if (c
->flags
& DCERPC_DEBUG_PAD_CHECK
) {
678 ndr
->flags
|= LIBNDR_FLAG_PAD_CHECK
;
681 if (c
->flags
& DCERPC_NDR_REF_ALLOC
) {
682 ndr
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
685 if (c
->flags
& DCERPC_NDR64
) {
686 ndr
->flags
|= LIBNDR_FLAG_NDR64
;
693 parse a data blob into a ncacn_packet structure. This handles both
694 input and output packets
696 static NTSTATUS
ncacn_pull(struct dcecli_connection
*c
, DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
697 struct ncacn_packet
*pkt
)
699 struct ndr_pull
*ndr
;
700 enum ndr_err_code ndr_err
;
702 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
704 return NT_STATUS_NO_MEMORY
;
707 if (! (CVAL(blob
->data
, DCERPC_DREP_OFFSET
) & DCERPC_DREP_LE
)) {
708 ndr
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
711 if (CVAL(blob
->data
, DCERPC_PFC_OFFSET
) & DCERPC_PFC_FLAG_OBJECT_UUID
) {
712 ndr
->flags
|= LIBNDR_FLAG_OBJECT_PRESENT
;
715 ndr_err
= ndr_pull_ncacn_packet(ndr
, NDR_SCALARS
|NDR_BUFFERS
, pkt
);
716 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
717 return ndr_map_error2ntstatus(ndr_err
);
720 if (pkt
->frag_length
!= blob
->length
) {
721 return NT_STATUS_RPC_PROTOCOL_ERROR
;
728 parse the authentication information on a dcerpc response packet
730 static NTSTATUS
ncacn_pull_request_auth(struct dcecli_connection
*c
, TALLOC_CTX
*mem_ctx
,
731 DATA_BLOB
*raw_packet
,
732 struct ncacn_packet
*pkt
)
735 struct dcerpc_auth auth
;
736 uint32_t auth_length
;
738 if (!c
->security_state
.auth_info
||
739 !c
->security_state
.generic_state
) {
743 switch (c
->security_state
.auth_info
->auth_level
) {
744 case DCERPC_AUTH_LEVEL_PRIVACY
:
745 case DCERPC_AUTH_LEVEL_INTEGRITY
:
748 case DCERPC_AUTH_LEVEL_CONNECT
:
749 if (pkt
->auth_length
!= 0) {
753 case DCERPC_AUTH_LEVEL_NONE
:
754 if (pkt
->auth_length
!= 0) {
755 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
760 return NT_STATUS_INVALID_LEVEL
;
763 status
= dcerpc_pull_auth_trailer(pkt
, mem_ctx
,
764 &pkt
->u
.response
.stub_and_verifier
,
765 &auth
, &auth_length
, false);
766 NT_STATUS_NOT_OK_RETURN(status
);
768 pkt
->u
.response
.stub_and_verifier
.length
-= auth_length
;
770 /* check signature or unseal the packet */
771 switch (c
->security_state
.auth_info
->auth_level
) {
772 case DCERPC_AUTH_LEVEL_PRIVACY
:
773 status
= gensec_unseal_packet(c
->security_state
.generic_state
,
774 raw_packet
->data
+ DCERPC_REQUEST_LENGTH
,
775 pkt
->u
.response
.stub_and_verifier
.length
,
777 raw_packet
->length
- auth
.credentials
.length
,
779 memcpy(pkt
->u
.response
.stub_and_verifier
.data
,
780 raw_packet
->data
+ DCERPC_REQUEST_LENGTH
,
781 pkt
->u
.response
.stub_and_verifier
.length
);
784 case DCERPC_AUTH_LEVEL_INTEGRITY
:
785 status
= gensec_check_packet(c
->security_state
.generic_state
,
786 pkt
->u
.response
.stub_and_verifier
.data
,
787 pkt
->u
.response
.stub_and_verifier
.length
,
789 raw_packet
->length
- auth
.credentials
.length
,
793 case DCERPC_AUTH_LEVEL_CONNECT
:
794 /* for now we ignore possible signatures here */
795 status
= NT_STATUS_OK
;
799 status
= NT_STATUS_INVALID_LEVEL
;
803 /* remove the indicated amount of padding */
804 if (pkt
->u
.response
.stub_and_verifier
.length
< auth
.auth_pad_length
) {
805 return NT_STATUS_INFO_LENGTH_MISMATCH
;
807 pkt
->u
.response
.stub_and_verifier
.length
-= auth
.auth_pad_length
;
814 push a dcerpc request packet into a blob, possibly signing it.
816 static NTSTATUS
ncacn_push_request_sign(struct dcecli_connection
*c
,
817 DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
819 struct ncacn_packet
*pkt
)
822 struct ndr_push
*ndr
;
824 size_t payload_length
;
825 enum ndr_err_code ndr_err
;
826 size_t hdr_size
= DCERPC_REQUEST_LENGTH
;
828 /* non-signed packets are simpler */
830 return ncacn_push_auth(blob
, mem_ctx
, pkt
, NULL
);
833 switch (c
->security_state
.auth_info
->auth_level
) {
834 case DCERPC_AUTH_LEVEL_PRIVACY
:
835 case DCERPC_AUTH_LEVEL_INTEGRITY
:
838 case DCERPC_AUTH_LEVEL_CONNECT
:
839 /* TODO: let the gensec mech decide if it wants to generate a signature */
840 return ncacn_push_auth(blob
, mem_ctx
, pkt
, NULL
);
842 case DCERPC_AUTH_LEVEL_NONE
:
843 return ncacn_push_auth(blob
, mem_ctx
, pkt
, NULL
);
846 return NT_STATUS_INVALID_LEVEL
;
849 ndr
= ndr_push_init_ctx(mem_ctx
);
851 return NT_STATUS_NO_MEMORY
;
854 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
855 ndr
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
858 if (c
->flags
& DCERPC_NDR64
) {
859 ndr
->flags
|= LIBNDR_FLAG_NDR64
;
862 if (pkt
->pfc_flags
& DCERPC_PFC_FLAG_OBJECT_UUID
) {
863 ndr
->flags
|= LIBNDR_FLAG_OBJECT_PRESENT
;
867 ndr_err
= ndr_push_ncacn_packet(ndr
, NDR_SCALARS
|NDR_BUFFERS
, pkt
);
868 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
869 return ndr_map_error2ntstatus(ndr_err
);
872 /* pad to 16 byte multiple in the payload portion of the
873 packet. This matches what w2k3 does. Note that we can't use
874 ndr_push_align() as that is relative to the start of the
875 whole packet, whereas w2k8 wants it relative to the start
877 c
->security_state
.auth_info
->auth_pad_length
=
878 (16 - (pkt
->u
.request
.stub_and_verifier
.length
& 15)) & 15;
879 ndr_err
= ndr_push_zero(ndr
, c
->security_state
.auth_info
->auth_pad_length
);
880 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
881 return ndr_map_error2ntstatus(ndr_err
);
884 payload_length
= pkt
->u
.request
.stub_and_verifier
.length
+
885 c
->security_state
.auth_info
->auth_pad_length
;
887 /* we start without signature, it will appended later */
888 c
->security_state
.auth_info
->credentials
= data_blob(NULL
,0);
890 /* add the auth verifier */
891 ndr_err
= ndr_push_dcerpc_auth(ndr
, NDR_SCALARS
|NDR_BUFFERS
, c
->security_state
.auth_info
);
892 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
893 return ndr_map_error2ntstatus(ndr_err
);
896 /* extract the whole packet as a blob */
897 *blob
= ndr_push_blob(ndr
);
900 * Setup the frag and auth length in the packet buffer.
901 * This is needed if the GENSEC mech does AEAD signing
902 * of the packet headers. The signature itself will be
905 dcerpc_set_frag_length(blob
, blob
->length
+ sig_size
);
906 dcerpc_set_auth_length(blob
, sig_size
);
908 /* sign or seal the packet */
909 switch (c
->security_state
.auth_info
->auth_level
) {
910 case DCERPC_AUTH_LEVEL_PRIVACY
:
911 status
= gensec_seal_packet(c
->security_state
.generic_state
,
913 blob
->data
+ hdr_size
,
918 if (!NT_STATUS_IS_OK(status
)) {
923 case DCERPC_AUTH_LEVEL_INTEGRITY
:
924 status
= gensec_sign_packet(c
->security_state
.generic_state
,
926 blob
->data
+ hdr_size
,
931 if (!NT_STATUS_IS_OK(status
)) {
937 status
= NT_STATUS_INVALID_LEVEL
;
941 if (creds2
.length
!= sig_size
) {
942 /* this means the sig_size estimate for the signature
943 was incorrect. We have to correct the packet
944 sizes. That means we could go over the max fragment
946 DEBUG(3,("ncacn_push_request_sign: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n",
947 (unsigned) creds2
.length
,
949 (unsigned) c
->security_state
.auth_info
->auth_pad_length
,
950 (unsigned) pkt
->u
.request
.stub_and_verifier
.length
));
951 dcerpc_set_frag_length(blob
, blob
->length
+ creds2
.length
);
952 dcerpc_set_auth_length(blob
, creds2
.length
);
955 if (!data_blob_append(mem_ctx
, blob
, creds2
.data
, creds2
.length
)) {
956 return NT_STATUS_NO_MEMORY
;
964 fill in the fixed values in a dcerpc header
966 static void init_ncacn_hdr(struct dcecli_connection
*c
, struct ncacn_packet
*pkt
)
969 pkt
->rpc_vers_minor
= 0;
970 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
973 pkt
->drep
[0] = DCERPC_DREP_LE
;
981 map a bind nak reason to a NTSTATUS
983 static NTSTATUS
dcerpc_map_reason(uint16_t reason
)
986 case DCERPC_BIND_REASON_ASYNTAX
:
987 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX
;
988 case DCERPC_BIND_REASON_INVALID_AUTH_TYPE
:
989 return NT_STATUS_INVALID_PARAMETER
;
991 return NT_STATUS_UNSUCCESSFUL
;
995 remove requests from the pending or queued queues
997 static int dcerpc_req_dequeue(struct rpc_request
*req
)
999 switch (req
->state
) {
1000 case RPC_REQUEST_QUEUED
:
1001 DLIST_REMOVE(req
->p
->conn
->request_queue
, req
);
1003 case RPC_REQUEST_PENDING
:
1004 DLIST_REMOVE(req
->p
->conn
->pending
, req
);
1006 case RPC_REQUEST_DONE
:
1014 mark the dcerpc connection dead. All outstanding requests get an error
1016 static void dcerpc_connection_dead(struct dcecli_connection
*conn
, NTSTATUS status
)
1018 if (conn
->dead
) return;
1022 TALLOC_FREE(conn
->io_trigger
);
1023 conn
->io_trigger_pending
= false;
1025 conn
->transport
.recv_data
= NULL
;
1027 if (conn
->transport
.shutdown_pipe
) {
1028 conn
->transport
.shutdown_pipe(conn
, status
);
1031 /* all pending requests get the error */
1032 while (conn
->pending
) {
1033 struct rpc_request
*req
= conn
->pending
;
1034 dcerpc_req_dequeue(req
);
1035 req
->state
= RPC_REQUEST_DONE
;
1036 req
->status
= status
;
1037 if (req
->async
.callback
) {
1038 req
->async
.callback(req
);
1042 /* all requests, which are not shipped */
1043 while (conn
->request_queue
) {
1044 struct rpc_request
*req
= conn
->request_queue
;
1045 dcerpc_req_dequeue(req
);
1046 req
->state
= RPC_REQUEST_DONE
;
1047 req
->status
= status
;
1048 if (req
->async
.callback
) {
1049 req
->async
.callback(req
);
1053 talloc_set_destructor(conn
, NULL
);
1054 if (conn
->free_skipped
) {
1060 forward declarations of the recv_data handlers for the types of
1061 packets we need to handle
1063 static void dcerpc_request_recv_data(struct dcecli_connection
*c
,
1064 DATA_BLOB
*raw_packet
, struct ncacn_packet
*pkt
);
1067 receive a dcerpc reply from the transport. Here we work out what
1068 type of reply it is (normal request, bind or alter context) and
1069 dispatch to the appropriate handler
1071 static void dcerpc_recv_data(struct dcecli_connection
*conn
, DATA_BLOB
*blob
, NTSTATUS status
)
1073 struct ncacn_packet pkt
;
1075 if (NT_STATUS_IS_OK(status
) && blob
->length
== 0) {
1076 status
= NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
1079 /* the transport may be telling us of a severe error, such as
1081 if (!NT_STATUS_IS_OK(status
)) {
1082 data_blob_free(blob
);
1083 dcerpc_connection_dead(conn
, status
);
1087 /* parse the basic packet to work out what type of response this is */
1088 status
= ncacn_pull(conn
, blob
, blob
->data
, &pkt
);
1089 if (!NT_STATUS_IS_OK(status
)) {
1090 data_blob_free(blob
);
1091 dcerpc_connection_dead(conn
, status
);
1095 dcerpc_request_recv_data(conn
, blob
, &pkt
);
1099 handle timeouts of individual dcerpc requests
1101 static void dcerpc_timeout_handler(struct tevent_context
*ev
, struct tevent_timer
*te
,
1102 struct timeval t
, void *private_data
)
1104 struct rpc_request
*req
= talloc_get_type(private_data
, struct rpc_request
);
1106 if (req
->ignore_timeout
) {
1107 dcerpc_req_dequeue(req
);
1108 req
->state
= RPC_REQUEST_DONE
;
1109 req
->status
= NT_STATUS_IO_TIMEOUT
;
1110 if (req
->async
.callback
) {
1111 req
->async
.callback(req
);
1116 dcerpc_connection_dead(req
->p
->conn
, NT_STATUS_IO_TIMEOUT
);
1119 struct dcerpc_bind_state
{
1120 struct tevent_context
*ev
;
1121 struct dcerpc_pipe
*p
;
1124 static void dcerpc_bind_fail_handler(struct rpc_request
*subreq
);
1125 static void dcerpc_bind_recv_handler(struct rpc_request
*subreq
,
1126 DATA_BLOB
*raw_packet
,
1127 struct ncacn_packet
*pkt
);
1129 struct tevent_req
*dcerpc_bind_send(TALLOC_CTX
*mem_ctx
,
1130 struct tevent_context
*ev
,
1131 struct dcerpc_pipe
*p
,
1132 const struct ndr_syntax_id
*syntax
,
1133 const struct ndr_syntax_id
*transfer_syntax
)
1135 struct tevent_req
*req
;
1136 struct dcerpc_bind_state
*state
;
1137 struct ncacn_packet pkt
;
1140 struct rpc_request
*subreq
;
1142 req
= tevent_req_create(mem_ctx
, &state
,
1143 struct dcerpc_bind_state
);
1151 p
->syntax
= *syntax
;
1152 p
->transfer_syntax
= *transfer_syntax
;
1154 init_ncacn_hdr(p
->conn
, &pkt
);
1156 pkt
.ptype
= DCERPC_PKT_BIND
;
1157 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
1158 pkt
.call_id
= p
->conn
->call_id
;
1159 pkt
.auth_length
= 0;
1161 if (p
->binding
->flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
1162 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
1165 if (p
->binding
->flags
& DCERPC_HEADER_SIGNING
) {
1166 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
;
1169 pkt
.u
.bind
.max_xmit_frag
= 5840;
1170 pkt
.u
.bind
.max_recv_frag
= 5840;
1171 pkt
.u
.bind
.assoc_group_id
= p
->binding
->assoc_group_id
;
1172 pkt
.u
.bind
.num_contexts
= 1;
1173 pkt
.u
.bind
.ctx_list
= talloc_array(mem_ctx
, struct dcerpc_ctx_list
, 1);
1174 if (tevent_req_nomem(pkt
.u
.bind
.ctx_list
, req
)) {
1175 return tevent_req_post(req
, ev
);
1177 pkt
.u
.bind
.ctx_list
[0].context_id
= p
->context_id
;
1178 pkt
.u
.bind
.ctx_list
[0].num_transfer_syntaxes
= 1;
1179 pkt
.u
.bind
.ctx_list
[0].abstract_syntax
= p
->syntax
;
1180 pkt
.u
.bind
.ctx_list
[0].transfer_syntaxes
= &p
->transfer_syntax
;
1181 pkt
.u
.bind
.auth_info
= data_blob(NULL
, 0);
1183 /* construct the NDR form of the packet */
1184 status
= ncacn_push_auth(&blob
, state
, &pkt
,
1185 p
->conn
->security_state
.auth_info
);
1186 if (tevent_req_nterror(req
, status
)) {
1187 return tevent_req_post(req
, ev
);
1190 p
->conn
->transport
.recv_data
= dcerpc_recv_data
;
1193 * we allocate a dcerpc_request so we can be in the same
1194 * request queue as normal requests
1196 subreq
= talloc_zero(state
, struct rpc_request
);
1197 if (tevent_req_nomem(subreq
, req
)) {
1198 return tevent_req_post(req
, ev
);
1201 subreq
->state
= RPC_REQUEST_PENDING
;
1202 subreq
->call_id
= pkt
.call_id
;
1203 subreq
->async
.private_data
= req
;
1204 subreq
->async
.callback
= dcerpc_bind_fail_handler
;
1206 subreq
->recv_handler
= dcerpc_bind_recv_handler
;
1207 DLIST_ADD_END(p
->conn
->pending
, subreq
, struct rpc_request
*);
1208 talloc_set_destructor(subreq
, dcerpc_req_dequeue
);
1210 status
= p
->conn
->transport
.send_request(p
->conn
, &blob
, true);
1211 if (tevent_req_nterror(req
, status
)) {
1212 return tevent_req_post(req
, ev
);
1215 tevent_add_timer(ev
, subreq
,
1216 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT
, 0),
1217 dcerpc_timeout_handler
, subreq
);
1222 static void dcerpc_bind_fail_handler(struct rpc_request
*subreq
)
1224 struct tevent_req
*req
=
1225 talloc_get_type_abort(subreq
->async
.private_data
,
1227 struct dcerpc_bind_state
*state
=
1228 tevent_req_data(req
,
1229 struct dcerpc_bind_state
);
1230 NTSTATUS status
= subreq
->status
;
1232 TALLOC_FREE(subreq
);
1235 * We trigger the callback in the next event run
1236 * because the code in this file might trigger
1237 * multiple request callbacks from within a single
1240 * In order to avoid segfaults from within
1241 * dcerpc_connection_dead() we call
1242 * tevent_req_defer_callback().
1244 tevent_req_defer_callback(req
, state
->ev
);
1246 tevent_req_nterror(req
, status
);
1249 static void dcerpc_bind_recv_handler(struct rpc_request
*subreq
,
1250 DATA_BLOB
*raw_packet
,
1251 struct ncacn_packet
*pkt
)
1253 struct tevent_req
*req
=
1254 talloc_get_type_abort(subreq
->async
.private_data
,
1256 struct dcerpc_bind_state
*state
=
1257 tevent_req_data(req
,
1258 struct dcerpc_bind_state
);
1259 struct dcecli_connection
*conn
= state
->p
->conn
;
1263 * Note that pkt is allocated under raw_packet->data,
1264 * while raw_packet->data is a child of subreq.
1266 talloc_steal(state
, raw_packet
->data
);
1267 TALLOC_FREE(subreq
);
1270 * We trigger the callback in the next event run
1271 * because the code in this file might trigger
1272 * multiple request callbacks from within a single
1275 * In order to avoid segfaults from within
1276 * dcerpc_connection_dead() we call
1277 * tevent_req_defer_callback().
1279 tevent_req_defer_callback(req
, state
->ev
);
1281 if (pkt
->ptype
== DCERPC_PKT_BIND_NAK
) {
1282 status
= dcerpc_map_reason(pkt
->u
.bind_nak
.reject_reason
);
1284 DEBUG(2,("dcerpc: bind_nak reason %d - %s\n",
1285 pkt
->u
.bind_nak
.reject_reason
, nt_errstr(status
)));
1287 tevent_req_nterror(req
, status
);
1291 if ((pkt
->ptype
!= DCERPC_PKT_BIND_ACK
) ||
1292 (pkt
->u
.bind_ack
.num_results
== 0) ||
1293 (pkt
->u
.bind_ack
.ctx_list
[0].result
!= 0)) {
1294 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
1295 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
1299 conn
->srv_max_xmit_frag
= pkt
->u
.bind_ack
.max_xmit_frag
;
1300 conn
->srv_max_recv_frag
= pkt
->u
.bind_ack
.max_recv_frag
;
1302 if ((state
->p
->binding
->flags
& DCERPC_CONCURRENT_MULTIPLEX
) &&
1303 (pkt
->pfc_flags
& DCERPC_PFC_FLAG_CONC_MPX
)) {
1304 conn
->flags
|= DCERPC_CONCURRENT_MULTIPLEX
;
1307 if ((state
->p
->binding
->flags
& DCERPC_HEADER_SIGNING
) &&
1308 (pkt
->pfc_flags
& DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
)) {
1309 conn
->flags
|= DCERPC_HEADER_SIGNING
;
1312 /* the bind_ack might contain a reply set of credentials */
1313 if (conn
->security_state
.auth_info
&& pkt
->u
.bind_ack
.auth_info
.length
) {
1314 uint32_t auth_length
;
1316 status
= dcerpc_pull_auth_trailer(pkt
, conn
, &pkt
->u
.bind_ack
.auth_info
,
1317 conn
->security_state
.auth_info
, &auth_length
, true);
1318 if (tevent_req_nterror(req
, status
)) {
1323 state
->p
->assoc_group_id
= pkt
->u
.bind_ack
.assoc_group_id
;
1325 tevent_req_done(req
);
1328 NTSTATUS
dcerpc_bind_recv(struct tevent_req
*req
)
1330 return tevent_req_simple_recv_ntstatus(req
);
1334 perform a continued bind (and auth3)
1336 NTSTATUS
dcerpc_auth3(struct dcerpc_pipe
*p
,
1337 TALLOC_CTX
*mem_ctx
)
1339 struct ncacn_packet pkt
;
1343 init_ncacn_hdr(p
->conn
, &pkt
);
1345 pkt
.ptype
= DCERPC_PKT_AUTH3
;
1346 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
1347 pkt
.call_id
= next_call_id(p
->conn
);
1348 pkt
.auth_length
= 0;
1349 pkt
.u
.auth3
.auth_info
= data_blob(NULL
, 0);
1351 if (p
->binding
->flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
1352 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
1355 if (p
->binding
->flags
& DCERPC_HEADER_SIGNING
) {
1356 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
;
1359 /* construct the NDR form of the packet */
1360 status
= ncacn_push_auth(&blob
, mem_ctx
,
1362 p
->conn
->security_state
.auth_info
);
1363 if (!NT_STATUS_IS_OK(status
)) {
1367 /* send it on its way */
1368 status
= p
->conn
->transport
.send_request(p
->conn
, &blob
, false);
1369 if (!NT_STATUS_IS_OK(status
)) {
1373 return NT_STATUS_OK
;
1378 process a fragment received from the transport layer during a
1381 This function frees the data
1383 static void dcerpc_request_recv_data(struct dcecli_connection
*c
,
1384 DATA_BLOB
*raw_packet
, struct ncacn_packet
*pkt
)
1386 struct rpc_request
*req
;
1387 unsigned int length
;
1388 NTSTATUS status
= NT_STATUS_OK
;
1391 if this is an authenticated connection then parse and check
1392 the auth info. We have to do this before finding the
1393 matching packet, as the request structure might have been
1394 removed due to a timeout, but if it has been we still need
1395 to run the auth routines so that we don't get the sign/seal
1396 info out of step with the server
1398 if (c
->security_state
.auth_info
&& c
->security_state
.generic_state
&&
1399 pkt
->ptype
== DCERPC_PKT_RESPONSE
) {
1400 status
= ncacn_pull_request_auth(c
, raw_packet
->data
, raw_packet
, pkt
);
1403 /* find the matching request */
1404 for (req
=c
->pending
;req
;req
=req
->next
) {
1405 if (pkt
->call_id
== req
->call_id
) break;
1409 /* useful for testing certain vendors RPC servers */
1410 if (req
== NULL
&& c
->pending
&& pkt
->call_id
== 0) {
1411 DEBUG(0,("HACK FOR INCORRECT CALL ID\n"));
1417 DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt
->call_id
));
1418 data_blob_free(raw_packet
);
1422 talloc_steal(req
, raw_packet
->data
);
1424 if (req
->recv_handler
!= NULL
) {
1425 dcerpc_req_dequeue(req
);
1426 req
->state
= RPC_REQUEST_DONE
;
1429 * We have to look at shipping further requests before calling
1430 * the async function, that one might close the pipe
1432 dcerpc_schedule_io_trigger(c
);
1434 req
->recv_handler(req
, raw_packet
, pkt
);
1438 if (pkt
->ptype
== DCERPC_PKT_FAULT
) {
1439 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c
, pkt
->u
.fault
.status
)));
1440 req
->fault_code
= pkt
->u
.fault
.status
;
1441 req
->status
= NT_STATUS_NET_WRITE_FAULT
;
1445 if (pkt
->ptype
!= DCERPC_PKT_RESPONSE
) {
1446 DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
1448 req
->fault_code
= DCERPC_FAULT_OTHER
;
1449 req
->status
= NT_STATUS_NET_WRITE_FAULT
;
1453 /* now check the status from the auth routines, and if it failed then fail
1454 this request accordingly */
1455 if (!NT_STATUS_IS_OK(status
)) {
1456 req
->status
= status
;
1460 length
= pkt
->u
.response
.stub_and_verifier
.length
;
1463 req
->payload
.data
= talloc_realloc(req
,
1466 req
->payload
.length
+ length
);
1467 if (!req
->payload
.data
) {
1468 req
->status
= NT_STATUS_NO_MEMORY
;
1471 memcpy(req
->payload
.data
+req
->payload
.length
,
1472 pkt
->u
.response
.stub_and_verifier
.data
, length
);
1473 req
->payload
.length
+= length
;
1476 if (!(pkt
->pfc_flags
& DCERPC_PFC_FLAG_LAST
)) {
1477 c
->transport
.send_read(c
);
1481 if (!(pkt
->drep
[0] & DCERPC_DREP_LE
)) {
1482 req
->flags
|= DCERPC_PULL_BIGENDIAN
;
1484 req
->flags
&= ~DCERPC_PULL_BIGENDIAN
;
1489 /* we've got the full payload */
1490 dcerpc_req_dequeue(req
);
1491 req
->state
= RPC_REQUEST_DONE
;
1494 * We have to look at shipping further requests before calling
1495 * the async function, that one might close the pipe
1497 dcerpc_schedule_io_trigger(c
);
1499 if (req
->async
.callback
) {
1500 req
->async
.callback(req
);
1505 perform the send side of a async dcerpc request
1507 static struct rpc_request
*dcerpc_request_send(TALLOC_CTX
*mem_ctx
,
1508 struct dcerpc_pipe
*p
,
1509 const struct GUID
*object
,
1511 DATA_BLOB
*stub_data
)
1513 struct rpc_request
*req
;
1515 p
->conn
->transport
.recv_data
= dcerpc_recv_data
;
1517 req
= talloc_zero(mem_ctx
, struct rpc_request
);
1523 req
->call_id
= next_call_id(p
->conn
);
1524 req
->state
= RPC_REQUEST_QUEUED
;
1526 if (object
!= NULL
) {
1527 req
->object
= (struct GUID
*)talloc_memdup(req
, (const void *)object
, sizeof(*object
));
1528 if (req
->object
== NULL
) {
1535 req
->request_data
.length
= stub_data
->length
;
1536 req
->request_data
.data
= stub_data
->data
;
1538 DLIST_ADD_END(p
->conn
->request_queue
, req
, struct rpc_request
*);
1539 talloc_set_destructor(req
, dcerpc_req_dequeue
);
1541 dcerpc_schedule_io_trigger(p
->conn
);
1543 if (p
->request_timeout
) {
1544 tevent_add_timer(dcerpc_event_context(p
), req
,
1545 timeval_current_ofs(p
->request_timeout
, 0),
1546 dcerpc_timeout_handler
, req
);
1553 Send a request using the transport
1556 static void dcerpc_ship_next_request(struct dcecli_connection
*c
)
1558 struct rpc_request
*req
;
1559 struct dcerpc_pipe
*p
;
1560 DATA_BLOB
*stub_data
;
1561 struct ncacn_packet pkt
;
1563 uint32_t remaining
, chunk_size
;
1564 bool first_packet
= true;
1565 size_t sig_size
= 0;
1566 bool need_async
= false;
1567 bool can_async
= true;
1569 req
= c
->request_queue
;
1575 stub_data
= &req
->request_data
;
1581 if (c
->security_state
.auth_info
&&
1582 c
->security_state
.generic_state
)
1584 struct gensec_security
*gensec
= c
->security_state
.generic_state
;
1586 switch (c
->security_state
.auth_info
->auth_level
) {
1587 case DCERPC_AUTH_LEVEL_PRIVACY
:
1588 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1589 can_async
= gensec_have_feature(gensec
,
1590 GENSEC_FEATURE_ASYNC_REPLIES
);
1592 case DCERPC_AUTH_LEVEL_CONNECT
:
1593 case DCERPC_AUTH_LEVEL_NONE
:
1602 if (need_async
&& !can_async
) {
1603 req
->wait_for_sync
= true;
1607 DLIST_REMOVE(c
->request_queue
, req
);
1608 DLIST_ADD(c
->pending
, req
);
1609 req
->state
= RPC_REQUEST_PENDING
;
1611 init_ncacn_hdr(p
->conn
, &pkt
);
1613 remaining
= stub_data
->length
;
1615 /* we can write a full max_recv_frag size, minus the dcerpc
1616 request header size */
1617 chunk_size
= p
->conn
->srv_max_recv_frag
;
1618 chunk_size
-= DCERPC_REQUEST_LENGTH
;
1619 if (c
->security_state
.auth_info
&&
1620 c
->security_state
.generic_state
) {
1621 sig_size
= gensec_sig_size(c
->security_state
.generic_state
,
1622 p
->conn
->srv_max_recv_frag
);
1624 chunk_size
-= DCERPC_AUTH_TRAILER_LENGTH
;
1625 chunk_size
-= sig_size
;
1628 chunk_size
-= (chunk_size
% 16);
1630 pkt
.ptype
= DCERPC_PKT_REQUEST
;
1631 pkt
.call_id
= req
->call_id
;
1632 pkt
.auth_length
= 0;
1634 pkt
.u
.request
.alloc_hint
= remaining
;
1635 pkt
.u
.request
.context_id
= p
->context_id
;
1636 pkt
.u
.request
.opnum
= req
->opnum
;
1639 pkt
.u
.request
.object
.object
= *req
->object
;
1640 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_OBJECT_UUID
;
1641 chunk_size
-= ndr_size_GUID(req
->object
,0);
1644 /* we send a series of pdus without waiting for a reply */
1645 while (remaining
> 0 || first_packet
) {
1646 uint32_t chunk
= MIN(chunk_size
, remaining
);
1647 bool last_frag
= false;
1648 bool do_trans
= false;
1650 first_packet
= false;
1651 pkt
.pfc_flags
&= ~(DCERPC_PFC_FLAG_FIRST
|DCERPC_PFC_FLAG_LAST
);
1653 if (remaining
== stub_data
->length
) {
1654 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_FIRST
;
1656 if (chunk
== remaining
) {
1657 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_LAST
;
1661 pkt
.u
.request
.stub_and_verifier
.data
= stub_data
->data
+
1662 (stub_data
->length
- remaining
);
1663 pkt
.u
.request
.stub_and_verifier
.length
= chunk
;
1665 req
->status
= ncacn_push_request_sign(p
->conn
, &blob
, req
, sig_size
, &pkt
);
1666 if (!NT_STATUS_IS_OK(req
->status
)) {
1667 req
->state
= RPC_REQUEST_DONE
;
1668 DLIST_REMOVE(p
->conn
->pending
, req
);
1672 if (last_frag
&& !need_async
) {
1676 req
->status
= p
->conn
->transport
.send_request(p
->conn
, &blob
, do_trans
);
1677 if (!NT_STATUS_IS_OK(req
->status
)) {
1678 req
->state
= RPC_REQUEST_DONE
;
1679 DLIST_REMOVE(p
->conn
->pending
, req
);
1683 if (last_frag
&& !do_trans
) {
1684 req
->status
= p
->conn
->transport
.send_read(p
->conn
);
1685 if (!NT_STATUS_IS_OK(req
->status
)) {
1686 req
->state
= RPC_REQUEST_DONE
;
1687 DLIST_REMOVE(p
->conn
->pending
, req
);
1696 static void dcerpc_io_trigger(struct tevent_context
*ctx
,
1697 struct tevent_immediate
*im
,
1700 struct dcecli_connection
*c
=
1701 talloc_get_type_abort(private_data
,
1702 struct dcecli_connection
);
1704 c
->io_trigger_pending
= false;
1706 dcerpc_schedule_io_trigger(c
);
1708 dcerpc_ship_next_request(c
);
1711 static void dcerpc_schedule_io_trigger(struct dcecli_connection
*c
)
1717 if (c
->request_queue
== NULL
) {
1721 if (c
->request_queue
->wait_for_sync
&& c
->pending
) {
1725 if (c
->io_trigger_pending
) {
1729 c
->io_trigger_pending
= true;
1731 tevent_schedule_immediate(c
->io_trigger
,
1738 return the event context for a dcerpc pipe
1739 used by callers who wish to operate asynchronously
1741 _PUBLIC_
struct tevent_context
*dcerpc_event_context(struct dcerpc_pipe
*p
)
1743 return p
->conn
->event_ctx
;
1749 perform the receive side of a async dcerpc request
1751 static NTSTATUS
dcerpc_request_recv(struct rpc_request
*req
,
1752 TALLOC_CTX
*mem_ctx
,
1753 DATA_BLOB
*stub_data
)
1757 while (req
->state
!= RPC_REQUEST_DONE
) {
1758 struct tevent_context
*ctx
= dcerpc_event_context(req
->p
);
1759 if (tevent_loop_once(ctx
) != 0) {
1760 return NT_STATUS_CONNECTION_DISCONNECTED
;
1763 *stub_data
= req
->payload
;
1764 status
= req
->status
;
1765 if (stub_data
->data
) {
1766 stub_data
->data
= talloc_steal(mem_ctx
, stub_data
->data
);
1768 if (NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
1769 req
->p
->last_fault_code
= req
->fault_code
;
1771 talloc_unlink(talloc_parent(req
), req
);
1776 this is a paranoid NDR validator. For every packet we push onto the wire
1777 we pull it back again, then push it again. Then we compare the raw NDR data
1778 for that to the NDR we initially generated. If they don't match then we know
1779 we must have a bug in either the pull or push side of our code
1781 static NTSTATUS
dcerpc_ndr_validate_in(struct dcecli_connection
*c
,
1782 TALLOC_CTX
*mem_ctx
,
1785 ndr_push_flags_fn_t ndr_push
,
1786 ndr_pull_flags_fn_t ndr_pull
)
1789 struct ndr_pull
*pull
;
1790 struct ndr_push
*push
;
1792 enum ndr_err_code ndr_err
;
1794 st
= talloc_size(mem_ctx
, struct_size
);
1796 return NT_STATUS_NO_MEMORY
;
1799 pull
= ndr_pull_init_flags(c
, &blob
, mem_ctx
);
1801 return NT_STATUS_NO_MEMORY
;
1803 pull
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
1805 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
1806 pull
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
1809 if (c
->flags
& DCERPC_NDR64
) {
1810 pull
->flags
|= LIBNDR_FLAG_NDR64
;
1813 ndr_err
= ndr_pull(pull
, NDR_IN
, st
);
1814 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1815 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1816 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
1817 "failed input validation pull - %s",
1819 return ndr_map_error2ntstatus(ndr_err
);
1822 push
= ndr_push_init_ctx(mem_ctx
);
1824 return NT_STATUS_NO_MEMORY
;
1827 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
1828 push
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
1831 if (c
->flags
& DCERPC_NDR64
) {
1832 push
->flags
|= LIBNDR_FLAG_NDR64
;
1835 ndr_err
= ndr_push(push
, NDR_IN
, st
);
1836 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1837 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1838 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
1839 "failed input validation push - %s",
1841 return ndr_map_error2ntstatus(ndr_err
);
1844 blob2
= ndr_push_blob(push
);
1846 if (data_blob_cmp(&blob
, &blob2
) != 0) {
1847 DEBUG(3,("original:\n"));
1848 dump_data(3, blob
.data
, blob
.length
);
1849 DEBUG(3,("secondary:\n"));
1850 dump_data(3, blob2
.data
, blob2
.length
);
1851 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
1852 "failed input validation blobs doesn't match");
1853 return ndr_map_error2ntstatus(ndr_err
);
1856 return NT_STATUS_OK
;
1860 this is a paranoid NDR input validator. For every packet we pull
1861 from the wire we push it back again then pull and push it
1862 again. Then we compare the raw NDR data for that to the NDR we
1863 initially generated. If they don't match then we know we must have a
1864 bug in either the pull or push side of our code
1866 static NTSTATUS
dcerpc_ndr_validate_out(struct dcecli_connection
*c
,
1867 struct ndr_pull
*pull_in
,
1870 ndr_push_flags_fn_t ndr_push
,
1871 ndr_pull_flags_fn_t ndr_pull
,
1872 ndr_print_function_t ndr_print
)
1875 struct ndr_pull
*pull
;
1876 struct ndr_push
*push
;
1877 DATA_BLOB blob
, blob2
;
1878 TALLOC_CTX
*mem_ctx
= pull_in
;
1880 enum ndr_err_code ndr_err
;
1882 st
= talloc_size(mem_ctx
, struct_size
);
1884 return NT_STATUS_NO_MEMORY
;
1886 memcpy(st
, struct_ptr
, struct_size
);
1888 push
= ndr_push_init_ctx(mem_ctx
);
1890 return NT_STATUS_NO_MEMORY
;
1893 ndr_err
= ndr_push(push
, NDR_OUT
, struct_ptr
);
1894 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1895 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1896 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
1897 "failed output validation push - %s",
1899 return ndr_map_error2ntstatus(ndr_err
);
1902 blob
= ndr_push_blob(push
);
1904 pull
= ndr_pull_init_flags(c
, &blob
, mem_ctx
);
1906 return NT_STATUS_NO_MEMORY
;
1909 pull
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
1910 ndr_err
= ndr_pull(pull
, NDR_OUT
, st
);
1911 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1912 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1913 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
1914 "failed output validation pull - %s",
1916 return ndr_map_error2ntstatus(ndr_err
);
1919 push
= ndr_push_init_ctx(mem_ctx
);
1921 return NT_STATUS_NO_MEMORY
;
1924 ndr_err
= ndr_push(push
, NDR_OUT
, st
);
1925 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1926 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1927 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
1928 "failed output validation push2 - %s",
1930 return ndr_map_error2ntstatus(ndr_err
);
1933 blob2
= ndr_push_blob(push
);
1935 if (data_blob_cmp(&blob
, &blob2
) != 0) {
1936 DEBUG(3,("original:\n"));
1937 dump_data(3, blob
.data
, blob
.length
);
1938 DEBUG(3,("secondary:\n"));
1939 dump_data(3, blob2
.data
, blob2
.length
);
1940 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
1941 "failed output validation blobs doesn't match");
1942 return ndr_map_error2ntstatus(ndr_err
);
1945 /* this checks the printed forms of the two structures, which effectively
1946 tests all of the value() attributes */
1947 s1
= ndr_print_function_string(mem_ctx
, ndr_print
, "VALIDATE",
1948 NDR_OUT
, struct_ptr
);
1949 s2
= ndr_print_function_string(mem_ctx
, ndr_print
, "VALIDATE",
1951 if (strcmp(s1
, s2
) != 0) {
1953 DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1
, s2
));
1955 /* this is sometimes useful */
1956 printf("VALIDATE ERROR\n");
1957 file_save("wire.dat", s1
, strlen(s1
));
1958 file_save("gen.dat", s2
, strlen(s2
));
1959 system("diff -u wire.dat gen.dat");
1961 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
1962 "failed output validation strings doesn't match");
1963 return ndr_map_error2ntstatus(ndr_err
);
1966 return NT_STATUS_OK
;
1970 a useful function for retrieving the server name we connected to
1972 _PUBLIC_
const char *dcerpc_server_name(struct dcerpc_pipe
*p
)
1974 if (!p
->conn
->transport
.target_hostname
) {
1975 if (!p
->conn
->transport
.peer_name
) {
1978 return p
->conn
->transport
.peer_name(p
->conn
);
1980 return p
->conn
->transport
.target_hostname(p
->conn
);
1985 get the dcerpc auth_level for a open connection
1987 uint32_t dcerpc_auth_level(struct dcecli_connection
*c
)
1991 if (c
->flags
& DCERPC_SEAL
) {
1992 auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
1993 } else if (c
->flags
& DCERPC_SIGN
) {
1994 auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
1995 } else if (c
->flags
& DCERPC_CONNECT
) {
1996 auth_level
= DCERPC_AUTH_LEVEL_CONNECT
;
1998 auth_level
= DCERPC_AUTH_LEVEL_NONE
;
2003 struct dcerpc_alter_context_state
{
2004 struct tevent_context
*ev
;
2005 struct dcerpc_pipe
*p
;
2008 static void dcerpc_alter_context_fail_handler(struct rpc_request
*subreq
);
2009 static void dcerpc_alter_context_recv_handler(struct rpc_request
*req
,
2010 DATA_BLOB
*raw_packet
,
2011 struct ncacn_packet
*pkt
);
2013 struct tevent_req
*dcerpc_alter_context_send(TALLOC_CTX
*mem_ctx
,
2014 struct tevent_context
*ev
,
2015 struct dcerpc_pipe
*p
,
2016 const struct ndr_syntax_id
*syntax
,
2017 const struct ndr_syntax_id
*transfer_syntax
)
2019 struct tevent_req
*req
;
2020 struct dcerpc_alter_context_state
*state
;
2021 struct ncacn_packet pkt
;
2024 struct rpc_request
*subreq
;
2026 req
= tevent_req_create(mem_ctx
, &state
,
2027 struct dcerpc_alter_context_state
);
2035 p
->syntax
= *syntax
;
2036 p
->transfer_syntax
= *transfer_syntax
;
2038 init_ncacn_hdr(p
->conn
, &pkt
);
2040 pkt
.ptype
= DCERPC_PKT_ALTER
;
2041 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
2042 pkt
.call_id
= p
->conn
->call_id
;
2043 pkt
.auth_length
= 0;
2045 if (p
->binding
->flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
2046 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
2049 if (p
->binding
->flags
& DCERPC_HEADER_SIGNING
) {
2050 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
;
2053 pkt
.u
.alter
.max_xmit_frag
= 5840;
2054 pkt
.u
.alter
.max_recv_frag
= 5840;
2055 pkt
.u
.alter
.assoc_group_id
= p
->binding
->assoc_group_id
;
2056 pkt
.u
.alter
.num_contexts
= 1;
2057 pkt
.u
.alter
.ctx_list
= talloc_array(state
, struct dcerpc_ctx_list
, 1);
2058 if (tevent_req_nomem(pkt
.u
.alter
.ctx_list
, req
)) {
2059 return tevent_req_post(req
, ev
);
2061 pkt
.u
.alter
.ctx_list
[0].context_id
= p
->context_id
;
2062 pkt
.u
.alter
.ctx_list
[0].num_transfer_syntaxes
= 1;
2063 pkt
.u
.alter
.ctx_list
[0].abstract_syntax
= p
->syntax
;
2064 pkt
.u
.alter
.ctx_list
[0].transfer_syntaxes
= &p
->transfer_syntax
;
2065 pkt
.u
.alter
.auth_info
= data_blob(NULL
, 0);
2067 /* construct the NDR form of the packet */
2068 status
= ncacn_push_auth(&blob
, state
, &pkt
,
2069 p
->conn
->security_state
.auth_info
);
2070 if (tevent_req_nterror(req
, status
)) {
2071 return tevent_req_post(req
, ev
);
2074 p
->conn
->transport
.recv_data
= dcerpc_recv_data
;
2077 * we allocate a dcerpc_request so we can be in the same
2078 * request queue as normal requests
2080 subreq
= talloc_zero(state
, struct rpc_request
);
2081 if (tevent_req_nomem(subreq
, req
)) {
2082 return tevent_req_post(req
, ev
);
2085 subreq
->state
= RPC_REQUEST_PENDING
;
2086 subreq
->call_id
= pkt
.call_id
;
2087 subreq
->async
.private_data
= req
;
2088 subreq
->async
.callback
= dcerpc_alter_context_fail_handler
;
2090 subreq
->recv_handler
= dcerpc_alter_context_recv_handler
;
2091 DLIST_ADD_END(p
->conn
->pending
, subreq
, struct rpc_request
*);
2092 talloc_set_destructor(subreq
, dcerpc_req_dequeue
);
2094 status
= p
->conn
->transport
.send_request(p
->conn
, &blob
, true);
2095 if (tevent_req_nterror(req
, status
)) {
2096 return tevent_req_post(req
, ev
);
2099 tevent_add_timer(ev
, subreq
,
2100 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT
, 0),
2101 dcerpc_timeout_handler
, subreq
);
2106 static void dcerpc_alter_context_fail_handler(struct rpc_request
*subreq
)
2108 struct tevent_req
*req
=
2109 talloc_get_type_abort(subreq
->async
.private_data
,
2111 struct dcerpc_alter_context_state
*state
=
2112 tevent_req_data(req
,
2113 struct dcerpc_alter_context_state
);
2114 NTSTATUS status
= subreq
->status
;
2116 TALLOC_FREE(subreq
);
2119 * We trigger the callback in the next event run
2120 * because the code in this file might trigger
2121 * multiple request callbacks from within a single
2124 * In order to avoid segfaults from within
2125 * dcerpc_connection_dead() we call
2126 * tevent_req_defer_callback().
2128 tevent_req_defer_callback(req
, state
->ev
);
2130 tevent_req_nterror(req
, status
);
2133 static void dcerpc_alter_context_recv_handler(struct rpc_request
*subreq
,
2134 DATA_BLOB
*raw_packet
,
2135 struct ncacn_packet
*pkt
)
2137 struct tevent_req
*req
=
2138 talloc_get_type_abort(subreq
->async
.private_data
,
2140 struct dcerpc_alter_context_state
*state
=
2141 tevent_req_data(req
,
2142 struct dcerpc_alter_context_state
);
2143 struct dcecli_connection
*conn
= state
->p
->conn
;
2147 * Note that pkt is allocated under raw_packet->data,
2148 * while raw_packet->data is a child of subreq.
2150 talloc_steal(state
, raw_packet
->data
);
2151 TALLOC_FREE(subreq
);
2154 * We trigger the callback in the next event run
2155 * because the code in this file might trigger
2156 * multiple request callbacks from within a single
2159 * In order to avoid segfaults from within
2160 * dcerpc_connection_dead() we call
2161 * tevent_req_defer_callback().
2163 tevent_req_defer_callback(req
, state
->ev
);
2165 if (pkt
->ptype
== DCERPC_PKT_ALTER_RESP
&&
2166 pkt
->u
.alter_resp
.num_results
== 1 &&
2167 pkt
->u
.alter_resp
.ctx_list
[0].result
!= 0) {
2168 status
= dcerpc_map_reason(pkt
->u
.alter_resp
.ctx_list
[0].reason
);
2169 DEBUG(2,("dcerpc: alter_resp failed - reason %d - %s\n",
2170 pkt
->u
.alter_resp
.ctx_list
[0].reason
,
2171 nt_errstr(status
)));
2172 tevent_req_nterror(req
, status
);
2176 if (pkt
->ptype
== DCERPC_PKT_FAULT
) {
2177 DEBUG(5,("dcerpc: alter_resp - rpc fault: %s\n",
2178 dcerpc_errstr(state
, pkt
->u
.fault
.status
)));
2179 if (pkt
->u
.fault
.status
== DCERPC_FAULT_ACCESS_DENIED
) {
2180 state
->p
->last_fault_code
= pkt
->u
.fault
.status
;
2181 tevent_req_nterror(req
, NT_STATUS_LOGON_FAILURE
);
2183 state
->p
->last_fault_code
= pkt
->u
.fault
.status
;
2184 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
2189 if (pkt
->ptype
!= DCERPC_PKT_ALTER_RESP
||
2190 pkt
->u
.alter_resp
.num_results
== 0 ||
2191 pkt
->u
.alter_resp
.ctx_list
[0].result
!= 0) {
2192 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
2193 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
2197 /* the alter_resp might contain a reply set of credentials */
2198 if (conn
->security_state
.auth_info
&&
2199 pkt
->u
.alter_resp
.auth_info
.length
) {
2200 uint32_t auth_length
;
2202 status
= dcerpc_pull_auth_trailer(pkt
, conn
, &pkt
->u
.alter_resp
.auth_info
,
2203 conn
->security_state
.auth_info
, &auth_length
, true);
2204 if (tevent_req_nterror(req
, status
)) {
2209 tevent_req_done(req
);
2212 NTSTATUS
dcerpc_alter_context_recv(struct tevent_req
*req
)
2214 return tevent_req_simple_recv_ntstatus(req
);
2218 send a dcerpc alter_context request
2220 _PUBLIC_ NTSTATUS
dcerpc_alter_context(struct dcerpc_pipe
*p
,
2221 TALLOC_CTX
*mem_ctx
,
2222 const struct ndr_syntax_id
*syntax
,
2223 const struct ndr_syntax_id
*transfer_syntax
)
2225 struct tevent_req
*subreq
;
2226 struct tevent_context
*ev
= p
->conn
->event_ctx
;
2229 /* TODO: create a new event context here */
2231 subreq
= dcerpc_alter_context_send(mem_ctx
, p
->conn
->event_ctx
,
2232 p
, syntax
, transfer_syntax
);
2233 if (subreq
== NULL
) {
2234 return NT_STATUS_NO_MEMORY
;
2237 ok
= tevent_req_poll(subreq
, ev
);
2240 status
= map_nt_error_from_unix_common(errno
);
2244 return dcerpc_alter_context_recv(subreq
);