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/>.
23 #define SOURCE4_LIBRPC_INTERNALS 1
26 #include "lib/util/util_file.h"
27 #include "system/filesys.h"
28 #include "../lib/util/dlinklist.h"
29 #include "lib/events/events.h"
30 #include "librpc/rpc/dcerpc.h"
31 #include "librpc/rpc/dcerpc_proto.h"
32 #include "librpc/rpc/dcerpc_util.h"
33 #include "librpc/rpc/dcerpc_pkt_auth.h"
34 #include "librpc/gen_ndr/ndr_misc.h"
35 #include "librpc/gen_ndr/ndr_dcerpc.h"
36 #include "auth/gensec/gensec.h"
37 #include "param/param.h"
38 #include "lib/util/tevent_ntstatus.h"
39 #include "librpc/rpc/rpc_common.h"
40 #include "lib/tsocket/tsocket.h"
41 #include "libcli/smb/tstream_smbXcli_np.h"
44 enum rpc_request_state
{
51 handle for an async dcerpc request
54 struct rpc_request
*next
, *prev
;
55 struct dcerpc_pipe
*p
;
58 enum rpc_request_state state
;
63 /* this is used to distinguish bind and alter_context requests
64 from normal requests */
65 void (*recv_handler
)(struct rpc_request
*conn
,
66 DATA_BLOB
*blob
, struct ncacn_packet
*pkt
);
68 const struct GUID
*object
;
70 DATA_BLOB request_data
;
77 void (*callback
)(struct rpc_request
*);
82 _PUBLIC_ NTSTATUS
dcerpc_init(void)
87 static void dcerpc_connection_dead(struct dcecli_connection
*conn
, NTSTATUS status
);
88 static void dcerpc_schedule_io_trigger(struct dcecli_connection
*c
);
90 static struct rpc_request
*dcerpc_request_send(TALLOC_CTX
*mem_ctx
,
91 struct dcerpc_pipe
*p
,
92 const struct GUID
*object
,
94 DATA_BLOB
*stub_data
);
95 static NTSTATUS
dcerpc_request_recv(struct rpc_request
*req
,
97 DATA_BLOB
*stub_data
);
98 static NTSTATUS
dcerpc_ndr_validate_in(struct dcecli_connection
*c
,
102 ndr_push_flags_fn_t ndr_push
,
103 ndr_pull_flags_fn_t ndr_pull
);
104 static NTSTATUS
dcerpc_ndr_validate_out(struct dcecli_connection
*c
,
105 struct ndr_pull
*pull_in
,
108 ndr_push_flags_fn_t ndr_push
,
109 ndr_pull_flags_fn_t ndr_pull
,
110 ndr_print_function_t ndr_print
);
111 static NTSTATUS
dcerpc_shutdown_pipe(struct dcecli_connection
*p
, NTSTATUS status
);
112 static NTSTATUS
dcerpc_send_request(struct dcecli_connection
*p
, DATA_BLOB
*data
,
114 static NTSTATUS
dcerpc_send_read(struct dcecli_connection
*p
);
116 /* destroy a dcerpc connection */
117 static int dcerpc_connection_destructor(struct dcecli_connection
*conn
)
120 conn
->free_skipped
= true;
123 dcerpc_connection_dead(conn
, NT_STATUS_LOCAL_DISCONNECT
);
128 /* initialise a dcerpc connection.
129 the event context is optional
131 static struct dcecli_connection
*dcerpc_connection_init(TALLOC_CTX
*mem_ctx
,
132 struct tevent_context
*ev
)
134 struct dcecli_connection
*c
;
136 c
= talloc_zero(mem_ctx
, struct dcecli_connection
);
143 if (c
->event_ctx
== NULL
) {
149 c
->security_state
.auth_type
= DCERPC_AUTH_TYPE_NONE
;
150 c
->security_state
.auth_level
= DCERPC_AUTH_LEVEL_NONE
;
151 c
->security_state
.auth_context_id
= 0;
152 c
->security_state
.session_key
= dcecli_generic_session_key
;
153 c
->security_state
.generic_state
= NULL
;
156 * Windows uses 5840 for ncacn_ip_tcp,
157 * so we also use it (for every transport)
158 * by default. But we give the transport
159 * the chance to overwrite it.
161 c
->srv_max_xmit_frag
= 5840;
162 c
->srv_max_recv_frag
= 5840;
163 c
->max_total_response_size
= DCERPC_NCACN_RESPONSE_DEFAULT_MAX_SIZE
;
166 c
->io_trigger
= tevent_create_immediate(c
);
167 if (c
->io_trigger
== NULL
) {
172 talloc_set_destructor(c
, dcerpc_connection_destructor
);
177 struct dcerpc_bh_state
{
178 struct dcerpc_pipe
*p
;
181 static const struct dcerpc_binding
*dcerpc_bh_get_binding(struct dcerpc_binding_handle
*h
)
183 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
184 struct dcerpc_bh_state
);
186 return hs
->p
->binding
;
189 static bool dcerpc_bh_is_connected(struct dcerpc_binding_handle
*h
)
191 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
192 struct dcerpc_bh_state
);
202 if (hs
->p
->conn
->dead
) {
209 static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle
*h
,
212 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
213 struct dcerpc_bh_state
);
217 return DCERPC_REQUEST_TIMEOUT
;
220 old
= hs
->p
->request_timeout
;
221 hs
->p
->request_timeout
= timeout
;
226 static bool dcerpc_bh_transport_encrypted(struct dcerpc_binding_handle
*h
)
228 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
229 struct dcerpc_bh_state
);
235 if (hs
->p
->conn
== NULL
) {
239 return hs
->p
->conn
->transport
.encrypted
;
242 static NTSTATUS
dcerpc_bh_transport_session_key(struct dcerpc_binding_handle
*h
,
244 DATA_BLOB
*session_key
)
246 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
247 struct dcerpc_bh_state
);
248 struct dcecli_security
*sec
= NULL
;
249 DATA_BLOB sk
= { .length
= 0, };
253 return NT_STATUS_NO_USER_SESSION_KEY
;
256 if (hs
->p
->conn
== NULL
) {
257 return NT_STATUS_NO_USER_SESSION_KEY
;
260 sec
= &hs
->p
->conn
->security_state
;
262 if (sec
->session_key
== NULL
) {
263 return NT_STATUS_NO_USER_SESSION_KEY
;
266 status
= sec
->session_key(hs
->p
->conn
, &sk
);
267 if (!NT_STATUS_IS_OK(status
)) {
271 sk
.length
= MIN(sk
.length
, 16);
273 *session_key
= data_blob_dup_talloc(mem_ctx
, sk
);
274 if (session_key
->length
!= sk
.length
) {
275 return NT_STATUS_NO_MEMORY
;
277 talloc_keep_secret(session_key
->data
);
281 static void dcerpc_bh_auth_info(struct dcerpc_binding_handle
*h
,
282 enum dcerpc_AuthType
*auth_type
,
283 enum dcerpc_AuthLevel
*auth_level
)
285 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
286 struct dcerpc_bh_state
);
292 if (hs
->p
->conn
== NULL
) {
296 *auth_type
= hs
->p
->conn
->security_state
.auth_type
;
297 *auth_level
= hs
->p
->conn
->security_state
.auth_level
;
300 static NTSTATUS
dcerpc_bh_auth_session_key(struct dcerpc_binding_handle
*h
,
302 DATA_BLOB
*session_key
)
304 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
305 struct dcerpc_bh_state
);
306 struct dcecli_security
*sec
= NULL
;
310 return NT_STATUS_NO_USER_SESSION_KEY
;
313 if (hs
->p
->conn
== NULL
) {
314 return NT_STATUS_NO_USER_SESSION_KEY
;
317 sec
= &hs
->p
->conn
->security_state
;
319 if (sec
->auth_type
== DCERPC_AUTH_TYPE_NONE
) {
320 return NT_STATUS_NO_USER_SESSION_KEY
;
323 if (sec
->generic_state
== NULL
) {
324 return NT_STATUS_NO_USER_SESSION_KEY
;
327 status
= gensec_session_key(sec
->generic_state
,
330 if (!NT_STATUS_IS_OK(status
)) {
334 talloc_keep_secret(session_key
->data
);
338 struct dcerpc_bh_raw_call_state
{
339 struct tevent_context
*ev
;
340 struct dcerpc_binding_handle
*h
;
346 static void dcerpc_bh_raw_call_done(struct rpc_request
*subreq
);
348 static struct tevent_req
*dcerpc_bh_raw_call_send(TALLOC_CTX
*mem_ctx
,
349 struct tevent_context
*ev
,
350 struct dcerpc_binding_handle
*h
,
351 const struct GUID
*object
,
354 const uint8_t *in_data
,
357 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
358 struct dcerpc_bh_state
);
359 struct tevent_req
*req
;
360 struct dcerpc_bh_raw_call_state
*state
;
362 struct rpc_request
*subreq
;
364 req
= tevent_req_create(mem_ctx
, &state
,
365 struct dcerpc_bh_raw_call_state
);
371 state
->in_data
.data
= discard_const_p(uint8_t, in_data
);
372 state
->in_data
.length
= in_length
;
374 ok
= dcerpc_bh_is_connected(h
);
376 tevent_req_nterror(req
, NT_STATUS_CONNECTION_DISCONNECTED
);
377 return tevent_req_post(req
, ev
);
380 subreq
= dcerpc_request_send(state
,
385 if (tevent_req_nomem(subreq
, req
)) {
386 return tevent_req_post(req
, ev
);
388 subreq
->async
.callback
= dcerpc_bh_raw_call_done
;
389 subreq
->async
.private_data
= req
;
394 static void dcerpc_bh_raw_call_done(struct rpc_request
*subreq
)
396 struct tevent_req
*req
=
397 talloc_get_type_abort(subreq
->async
.private_data
,
399 struct dcerpc_bh_raw_call_state
*state
=
401 struct dcerpc_bh_raw_call_state
);
405 state
->out_flags
= 0;
406 if (subreq
->flags
& DCERPC_PULL_BIGENDIAN
) {
407 state
->out_flags
|= LIBNDR_FLAG_BIGENDIAN
;
410 fault_code
= subreq
->fault_code
;
412 status
= dcerpc_request_recv(subreq
, state
, &state
->out_data
);
413 if (NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
414 status
= dcerpc_fault_to_nt_status(fault_code
);
418 * We trigger the callback in the next event run
419 * because the code in this file might trigger
420 * multiple request callbacks from within a single
423 * In order to avoid segfaults from within
424 * dcerpc_connection_dead() we call
425 * tevent_req_defer_callback().
427 tevent_req_defer_callback(req
, state
->ev
);
429 if (!NT_STATUS_IS_OK(status
)) {
430 tevent_req_nterror(req
, status
);
434 tevent_req_done(req
);
437 static NTSTATUS
dcerpc_bh_raw_call_recv(struct tevent_req
*req
,
443 struct dcerpc_bh_raw_call_state
*state
=
445 struct dcerpc_bh_raw_call_state
);
448 if (tevent_req_is_nterror(req
, &status
)) {
449 tevent_req_received(req
);
453 *out_data
= talloc_move(mem_ctx
, &state
->out_data
.data
);
454 *out_length
= state
->out_data
.length
;
455 *out_flags
= state
->out_flags
;
456 tevent_req_received(req
);
460 struct dcerpc_bh_disconnect_state
{
464 static struct tevent_req
*dcerpc_bh_disconnect_send(TALLOC_CTX
*mem_ctx
,
465 struct tevent_context
*ev
,
466 struct dcerpc_binding_handle
*h
)
468 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
469 struct dcerpc_bh_state
);
470 struct tevent_req
*req
;
471 struct dcerpc_bh_disconnect_state
*state
;
474 req
= tevent_req_create(mem_ctx
, &state
,
475 struct dcerpc_bh_disconnect_state
);
480 ok
= dcerpc_bh_is_connected(h
);
482 tevent_req_nterror(req
, NT_STATUS_CONNECTION_DISCONNECTED
);
483 return tevent_req_post(req
, ev
);
486 /* TODO: do a real disconnect ... */
489 tevent_req_done(req
);
490 return tevent_req_post(req
, ev
);
493 static NTSTATUS
dcerpc_bh_disconnect_recv(struct tevent_req
*req
)
497 if (tevent_req_is_nterror(req
, &status
)) {
498 tevent_req_received(req
);
502 tevent_req_received(req
);
506 static bool dcerpc_bh_push_bigendian(struct dcerpc_binding_handle
*h
)
508 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
509 struct dcerpc_bh_state
);
511 if (hs
->p
->conn
->flags
& DCERPC_PUSH_BIGENDIAN
) {
518 static bool dcerpc_bh_ref_alloc(struct dcerpc_binding_handle
*h
)
520 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
521 struct dcerpc_bh_state
);
523 if (hs
->p
->conn
->flags
& DCERPC_NDR_REF_ALLOC
) {
530 static bool dcerpc_bh_use_ndr64(struct dcerpc_binding_handle
*h
)
532 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
533 struct dcerpc_bh_state
);
535 if (hs
->p
->conn
->flags
& DCERPC_NDR64
) {
542 static void dcerpc_bh_do_ndr_print(struct dcerpc_binding_handle
*h
,
543 ndr_flags_type ndr_flags
,
544 const void *_struct_ptr
,
545 const struct ndr_interface_call
*call
)
547 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
548 struct dcerpc_bh_state
);
549 void *struct_ptr
= discard_const(_struct_ptr
);
550 bool print_in
= false;
551 bool print_out
= false;
553 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_PRINT_IN
) {
557 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_PRINT_OUT
) {
561 if (DEBUGLEVEL
>= 11) {
566 if (ndr_flags
& NDR_IN
) {
568 ndr_print_function_debug(call
->ndr_print
,
574 if (ndr_flags
& NDR_OUT
) {
576 ndr_print_function_debug(call
->ndr_print
,
584 static void dcerpc_bh_ndr_push_failed(struct dcerpc_binding_handle
*h
,
586 const void *struct_ptr
,
587 const struct ndr_interface_call
*call
)
589 DEBUG(2,("Unable to ndr_push structure for %s - %s\n",
590 call
->name
, nt_errstr(error
)));
593 static void dcerpc_bh_ndr_pull_failed(struct dcerpc_binding_handle
*h
,
595 const DATA_BLOB
*blob
,
596 const struct ndr_interface_call
*call
)
598 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
599 struct dcerpc_bh_state
);
600 const uint32_t num_examples
= 20;
603 DEBUG(2,("Unable to ndr_pull structure for %s - %s\n",
604 call
->name
, nt_errstr(error
)));
606 if (hs
->p
->conn
->packet_log_dir
== NULL
) return;
608 for (i
=0;i
<num_examples
;i
++) {
612 ret
= asprintf(&name
, "%s/rpclog/%s-out.%d",
613 hs
->p
->conn
->packet_log_dir
,
618 if (!file_exist(name
)) {
619 if (file_save(name
, blob
->data
, blob
->length
)) {
620 DEBUG(10,("Logged rpc packet to %s\n", name
));
629 static NTSTATUS
dcerpc_bh_ndr_validate_in(struct dcerpc_binding_handle
*h
,
631 const DATA_BLOB
*blob
,
632 const struct ndr_interface_call
*call
)
634 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
635 struct dcerpc_bh_state
);
637 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_VALIDATE_IN
) {
640 status
= dcerpc_ndr_validate_in(hs
->p
->conn
,
646 if (!NT_STATUS_IS_OK(status
)) {
647 DEBUG(0,("Validation [in] failed for %s - %s\n",
648 call
->name
, nt_errstr(status
)));
653 DEBUG(10,("rpc request data:\n"));
654 dump_data(10, blob
->data
, blob
->length
);
659 static NTSTATUS
dcerpc_bh_ndr_validate_out(struct dcerpc_binding_handle
*h
,
660 struct ndr_pull
*pull_in
,
661 const void *_struct_ptr
,
662 const struct ndr_interface_call
*call
)
664 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
665 struct dcerpc_bh_state
);
666 void *struct_ptr
= discard_const(_struct_ptr
);
668 DEBUG(10,("rpc reply data:\n"));
669 dump_data(10, pull_in
->data
, pull_in
->data_size
);
671 if (pull_in
->offset
!= pull_in
->data_size
) {
672 DEBUG(0,("Warning! ignoring %u unread bytes at ofs:%u (0x%08X) for %s!\n",
673 pull_in
->data_size
- pull_in
->offset
,
674 pull_in
->offset
, pull_in
->offset
,
676 /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here,
677 but it turns out that early versions of NT
678 (specifically NT3.1) add junk onto the end of rpc
679 packets, so if we want to interoperate at all with
680 those versions then we need to ignore this error */
683 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_VALIDATE_OUT
) {
686 status
= dcerpc_ndr_validate_out(hs
->p
->conn
,
693 if (!NT_STATUS_IS_OK(status
)) {
694 DEBUG(2,("Validation [out] failed for %s - %s\n",
695 call
->name
, nt_errstr(status
)));
703 static const struct dcerpc_binding_handle_ops dcerpc_bh_ops
= {
705 .get_binding
= dcerpc_bh_get_binding
,
706 .is_connected
= dcerpc_bh_is_connected
,
707 .set_timeout
= dcerpc_bh_set_timeout
,
708 .transport_encrypted
= dcerpc_bh_transport_encrypted
,
709 .transport_session_key
= dcerpc_bh_transport_session_key
,
710 .auth_info
= dcerpc_bh_auth_info
,
711 .auth_session_key
= dcerpc_bh_auth_session_key
,
712 .raw_call_send
= dcerpc_bh_raw_call_send
,
713 .raw_call_recv
= dcerpc_bh_raw_call_recv
,
714 .disconnect_send
= dcerpc_bh_disconnect_send
,
715 .disconnect_recv
= dcerpc_bh_disconnect_recv
,
717 .push_bigendian
= dcerpc_bh_push_bigendian
,
718 .ref_alloc
= dcerpc_bh_ref_alloc
,
719 .use_ndr64
= dcerpc_bh_use_ndr64
,
720 .do_ndr_print
= dcerpc_bh_do_ndr_print
,
721 .ndr_push_failed
= dcerpc_bh_ndr_push_failed
,
722 .ndr_pull_failed
= dcerpc_bh_ndr_pull_failed
,
723 .ndr_validate_in
= dcerpc_bh_ndr_validate_in
,
724 .ndr_validate_out
= dcerpc_bh_ndr_validate_out
,
727 /* initialise a dcerpc pipe. */
728 struct dcerpc_binding_handle
*dcerpc_pipe_binding_handle(struct dcerpc_pipe
*p
,
729 const struct GUID
*object
,
730 const struct ndr_interface_table
*table
)
732 struct dcerpc_binding_handle
*h
;
733 struct dcerpc_bh_state
*hs
;
735 h
= dcerpc_binding_handle_create(p
,
740 struct dcerpc_bh_state
,
747 dcerpc_binding_handle_set_sync_ev(h
, p
->conn
->event_ctx
);
752 /* initialise a dcerpc pipe. */
753 _PUBLIC_
struct dcerpc_pipe
*dcerpc_pipe_init(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
)
755 struct dcerpc_pipe
*p
;
757 p
= talloc_zero(mem_ctx
, struct dcerpc_pipe
);
762 p
->conn
= dcerpc_connection_init(p
, ev
);
763 if (p
->conn
== NULL
) {
768 p
->request_timeout
= DCERPC_REQUEST_TIMEOUT
;
771 p
->conn
->flags
|= DCERPC_DEBUG_PRINT_BOTH
;
779 choose the next call id to use
781 static uint32_t next_call_id(struct dcecli_connection
*c
)
784 if (c
->call_id
== 0) {
791 setup for a ndr pull, also setting up any flags from the binding string
793 static struct ndr_pull
*ndr_pull_init_flags(struct dcecli_connection
*c
,
794 DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
)
796 struct ndr_pull
*ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
798 if (ndr
== NULL
) return ndr
;
800 if (c
->flags
& DCERPC_DEBUG_PAD_CHECK
) {
801 ndr
->flags
|= LIBNDR_FLAG_PAD_CHECK
;
804 if (c
->flags
& DCERPC_NDR_REF_ALLOC
) {
805 ndr
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
808 if (c
->flags
& DCERPC_NDR64
) {
809 ndr
->flags
|= LIBNDR_FLAG_NDR64
;
816 parse the authentication information on a dcerpc response packet
818 static NTSTATUS
ncacn_pull_pkt_auth(struct dcecli_connection
*c
,
820 enum dcerpc_pkt_type ptype
,
821 uint8_t required_flags
,
822 uint8_t optional_flags
,
823 uint8_t payload_offset
,
824 DATA_BLOB
*payload_and_verifier
,
825 DATA_BLOB
*raw_packet
,
826 const struct ncacn_packet
*pkt
)
828 const struct dcerpc_auth tmp_auth
= {
829 .auth_type
= c
->security_state
.auth_type
,
830 .auth_level
= c
->security_state
.auth_level
,
831 .auth_context_id
= c
->security_state
.auth_context_id
,
835 status
= dcerpc_ncacn_pull_pkt_auth(&tmp_auth
,
836 c
->security_state
.generic_state
,
837 true, /* check_pkt_auth_fields */
843 payload_and_verifier
,
846 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROTOCOL_ERROR
)) {
847 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
849 if (!NT_STATUS_IS_OK(status
)) {
858 push a dcerpc request packet into a blob, possibly signing it.
860 static NTSTATUS
ncacn_push_request_sign(struct dcecli_connection
*c
,
861 DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
863 struct ncacn_packet
*pkt
)
865 const struct dcerpc_auth tmp_auth
= {
866 .auth_type
= c
->security_state
.auth_type
,
867 .auth_level
= c
->security_state
.auth_level
,
868 .auth_context_id
= c
->security_state
.auth_context_id
,
871 uint8_t payload_offset
= DCERPC_REQUEST_LENGTH
;
873 if (pkt
->pfc_flags
& DCERPC_PFC_FLAG_OBJECT_UUID
) {
874 payload_offset
+= 16;
877 status
= dcerpc_ncacn_push_pkt_auth(&tmp_auth
,
878 c
->security_state
.generic_state
,
882 &pkt
->u
.request
.stub_and_verifier
,
884 if (!NT_STATUS_IS_OK(status
)) {
893 fill in the fixed values in a dcerpc header
895 static void init_ncacn_hdr(struct dcecli_connection
*c
, struct ncacn_packet
*pkt
)
898 pkt
->rpc_vers_minor
= 0;
899 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
902 pkt
->drep
[0] = DCERPC_DREP_LE
;
910 map a bind nak reason to a NTSTATUS
912 static NTSTATUS
dcerpc_map_nak_reason(enum dcerpc_bind_nak_reason reason
)
915 case DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED
:
916 return NT_STATUS_REVISION_MISMATCH
;
917 case DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE
:
918 return NT_STATUS_INVALID_PARAMETER
;
922 return NT_STATUS_UNSUCCESSFUL
;
925 static NTSTATUS
dcerpc_map_ack_reason(const struct dcerpc_ack_ctx
*ack
)
928 return NT_STATUS_RPC_PROTOCOL_ERROR
;
931 switch (ack
->result
) {
932 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK
:
934 * We have not asked for this...
936 return NT_STATUS_RPC_PROTOCOL_ERROR
;
941 switch (ack
->reason
.value
) {
942 case DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED
:
943 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX
;
944 case DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED
:
945 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX
;
949 return NT_STATUS_UNSUCCESSFUL
;
953 remove requests from the pending or queued queues
955 static int dcerpc_req_dequeue(struct rpc_request
*req
)
957 switch (req
->state
) {
958 case RPC_REQUEST_QUEUED
:
959 DLIST_REMOVE(req
->p
->conn
->request_queue
, req
);
961 case RPC_REQUEST_PENDING
:
962 DLIST_REMOVE(req
->p
->conn
->pending
, req
);
964 case RPC_REQUEST_DONE
:
972 mark the dcerpc connection dead. All outstanding requests get an error
974 static void dcerpc_connection_dead(struct dcecli_connection
*conn
, NTSTATUS status
)
976 if (conn
->dead
) return;
980 TALLOC_FREE(conn
->io_trigger
);
981 conn
->io_trigger_pending
= false;
983 dcerpc_shutdown_pipe(conn
, status
);
985 /* all pending requests get the error */
986 while (conn
->pending
) {
987 struct rpc_request
*req
= conn
->pending
;
988 dcerpc_req_dequeue(req
);
989 req
->state
= RPC_REQUEST_DONE
;
990 req
->status
= status
;
991 if (req
->async
.callback
) {
992 req
->async
.callback(req
);
996 /* all requests, which are not shipped */
997 while (conn
->request_queue
) {
998 struct rpc_request
*req
= conn
->request_queue
;
999 dcerpc_req_dequeue(req
);
1000 req
->state
= RPC_REQUEST_DONE
;
1001 req
->status
= status
;
1002 if (req
->async
.callback
) {
1003 req
->async
.callback(req
);
1007 talloc_set_destructor(conn
, NULL
);
1008 if (conn
->free_skipped
) {
1014 forward declarations of the recv_data handlers for the types of
1015 packets we need to handle
1017 static void dcerpc_request_recv_data(struct dcecli_connection
*c
,
1018 DATA_BLOB
*raw_packet
, struct ncacn_packet
*pkt
);
1021 receive a dcerpc reply from the transport. Here we work out what
1022 type of reply it is (normal request, bind or alter context) and
1023 dispatch to the appropriate handler
1025 static void dcerpc_recv_data(struct dcecli_connection
*conn
, DATA_BLOB
*blob
, NTSTATUS status
)
1027 struct ncacn_packet pkt
;
1033 if (NT_STATUS_IS_OK(status
) && blob
->length
== 0) {
1034 status
= NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
1037 /* the transport may be telling us of a severe error, such as
1039 if (!NT_STATUS_IS_OK(status
)) {
1040 data_blob_free(blob
);
1041 dcerpc_connection_dead(conn
, status
);
1045 /* parse the basic packet to work out what type of response this is */
1046 status
= dcerpc_pull_ncacn_packet(blob
->data
, blob
, &pkt
);
1047 if (!NT_STATUS_IS_OK(status
)) {
1048 data_blob_free(blob
);
1049 dcerpc_connection_dead(conn
, status
);
1053 dcerpc_request_recv_data(conn
, blob
, &pkt
);
1057 handle timeouts of individual dcerpc requests
1059 static void dcerpc_timeout_handler(struct tevent_context
*ev
, struct tevent_timer
*te
,
1060 struct timeval t
, void *private_data
)
1062 struct rpc_request
*req
= talloc_get_type(private_data
, struct rpc_request
);
1064 if (req
->ignore_timeout
) {
1065 dcerpc_req_dequeue(req
);
1066 req
->state
= RPC_REQUEST_DONE
;
1067 req
->status
= NT_STATUS_IO_TIMEOUT
;
1068 if (req
->async
.callback
) {
1069 req
->async
.callback(req
);
1074 dcerpc_connection_dead(req
->p
->conn
, NT_STATUS_IO_TIMEOUT
);
1077 struct dcerpc_bind_state
{
1078 struct tevent_context
*ev
;
1079 struct dcerpc_pipe
*p
;
1082 static void dcerpc_bind_fail_handler(struct rpc_request
*subreq
);
1083 static void dcerpc_bind_recv_handler(struct rpc_request
*subreq
,
1084 DATA_BLOB
*raw_packet
,
1085 struct ncacn_packet
*pkt
);
1087 struct tevent_req
*dcerpc_bind_send(TALLOC_CTX
*mem_ctx
,
1088 struct tevent_context
*ev
,
1089 struct dcerpc_pipe
*p
,
1090 const struct ndr_syntax_id
*syntax
,
1091 const struct ndr_syntax_id
*transfer_syntax
)
1093 struct tevent_req
*req
;
1094 struct dcerpc_bind_state
*state
;
1095 struct ncacn_packet pkt
;
1098 struct rpc_request
*subreq
;
1100 struct ndr_syntax_id bind_time_features
;
1102 bind_time_features
= dcerpc_construct_bind_time_features(
1103 DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING
|
1104 DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN
);
1106 req
= tevent_req_create(mem_ctx
, &state
,
1107 struct dcerpc_bind_state
);
1115 p
->syntax
= *syntax
;
1116 p
->transfer_syntax
= *transfer_syntax
;
1118 flags
= dcerpc_binding_get_flags(p
->binding
);
1120 init_ncacn_hdr(p
->conn
, &pkt
);
1122 pkt
.ptype
= DCERPC_PKT_BIND
;
1123 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
1124 pkt
.call_id
= p
->conn
->call_id
;
1125 pkt
.auth_length
= 0;
1127 if (flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
1128 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
1131 if (p
->conn
->flags
& DCERPC_PROPOSE_HEADER_SIGNING
) {
1132 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
;
1135 pkt
.u
.bind
.max_xmit_frag
= p
->conn
->srv_max_xmit_frag
;
1136 pkt
.u
.bind
.max_recv_frag
= p
->conn
->srv_max_recv_frag
;
1137 pkt
.u
.bind
.assoc_group_id
= dcerpc_binding_get_assoc_group_id(p
->binding
);
1138 pkt
.u
.bind
.num_contexts
= 2;
1139 pkt
.u
.bind
.ctx_list
= talloc_zero_array(state
, struct dcerpc_ctx_list
,
1140 pkt
.u
.bind
.num_contexts
);
1141 if (tevent_req_nomem(pkt
.u
.bind
.ctx_list
, req
)) {
1142 return tevent_req_post(req
, ev
);
1144 pkt
.u
.bind
.ctx_list
[0].context_id
= p
->context_id
;
1145 pkt
.u
.bind
.ctx_list
[0].num_transfer_syntaxes
= 1;
1146 pkt
.u
.bind
.ctx_list
[0].abstract_syntax
= p
->syntax
;
1147 pkt
.u
.bind
.ctx_list
[0].transfer_syntaxes
= &p
->transfer_syntax
;
1148 pkt
.u
.bind
.ctx_list
[1].context_id
= p
->context_id
+ 1;
1149 pkt
.u
.bind
.ctx_list
[1].num_transfer_syntaxes
= 1;
1150 pkt
.u
.bind
.ctx_list
[1].abstract_syntax
= p
->syntax
;
1151 pkt
.u
.bind
.ctx_list
[1].transfer_syntaxes
= &bind_time_features
;
1152 pkt
.u
.bind
.auth_info
= data_blob(NULL
, 0);
1154 /* construct the NDR form of the packet */
1155 status
= dcerpc_ncacn_push_auth(&blob
,
1158 p
->conn
->security_state
.tmp_auth_info
.out
);
1159 if (tevent_req_nterror(req
, status
)) {
1160 return tevent_req_post(req
, ev
);
1164 * we allocate a dcerpc_request so we can be in the same
1165 * request queue as normal requests
1167 subreq
= talloc_zero(state
, struct rpc_request
);
1168 if (tevent_req_nomem(subreq
, req
)) {
1169 return tevent_req_post(req
, ev
);
1172 subreq
->state
= RPC_REQUEST_PENDING
;
1173 subreq
->call_id
= pkt
.call_id
;
1174 subreq
->async
.private_data
= req
;
1175 subreq
->async
.callback
= dcerpc_bind_fail_handler
;
1177 subreq
->recv_handler
= dcerpc_bind_recv_handler
;
1178 DLIST_ADD_END(p
->conn
->pending
, subreq
);
1179 talloc_set_destructor(subreq
, dcerpc_req_dequeue
);
1181 status
= dcerpc_send_request(p
->conn
, &blob
, true);
1182 if (tevent_req_nterror(req
, status
)) {
1183 return tevent_req_post(req
, ev
);
1186 tevent_add_timer(ev
, subreq
,
1187 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT
, 0),
1188 dcerpc_timeout_handler
, subreq
);
1193 static void dcerpc_bind_fail_handler(struct rpc_request
*subreq
)
1195 struct tevent_req
*req
=
1196 talloc_get_type_abort(subreq
->async
.private_data
,
1198 struct dcerpc_bind_state
*state
=
1199 tevent_req_data(req
,
1200 struct dcerpc_bind_state
);
1201 NTSTATUS status
= subreq
->status
;
1203 TALLOC_FREE(subreq
);
1206 * We trigger the callback in the next event run
1207 * because the code in this file might trigger
1208 * multiple request callbacks from within a single
1211 * In order to avoid segfaults from within
1212 * dcerpc_connection_dead() we call
1213 * tevent_req_defer_callback().
1215 tevent_req_defer_callback(req
, state
->ev
);
1217 tevent_req_nterror(req
, status
);
1220 static void dcerpc_bind_recv_handler(struct rpc_request
*subreq
,
1221 DATA_BLOB
*raw_packet
,
1222 struct ncacn_packet
*pkt
)
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 struct dcecli_connection
*conn
= state
->p
->conn
;
1231 struct dcecli_security
*sec
= &conn
->security_state
;
1232 struct dcerpc_binding
*b
= NULL
;
1237 * Note that pkt is allocated under raw_packet->data,
1238 * while raw_packet->data is a child of subreq.
1240 talloc_steal(state
, raw_packet
->data
);
1241 TALLOC_FREE(subreq
);
1244 * We trigger the callback in the next event run
1245 * because the code in this file might trigger
1246 * multiple request callbacks from within a single
1249 * In order to avoid segfaults from within
1250 * dcerpc_connection_dead() we call
1251 * tevent_req_defer_callback().
1253 tevent_req_defer_callback(req
, state
->ev
);
1255 if (pkt
->ptype
== DCERPC_PKT_BIND_NAK
) {
1256 status
= dcerpc_map_nak_reason(pkt
->u
.bind_nak
.reject_reason
);
1258 DEBUG(2,("dcerpc: bind_nak reason %d - %s\n",
1259 pkt
->u
.bind_nak
.reject_reason
, nt_errstr(status
)));
1261 tevent_req_nterror(req
, status
);
1265 status
= dcerpc_verify_ncacn_packet_header(pkt
,
1266 DCERPC_PKT_BIND_ACK
,
1267 pkt
->u
.bind_ack
.auth_info
.length
,
1268 DCERPC_PFC_FLAG_FIRST
|
1269 DCERPC_PFC_FLAG_LAST
,
1270 DCERPC_PFC_FLAG_CONC_MPX
|
1271 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
);
1272 if (!NT_STATUS_IS_OK(status
)) {
1273 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
1274 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
1278 if (pkt
->u
.bind_ack
.num_results
< 1) {
1279 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
1280 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
1284 if (pkt
->u
.bind_ack
.ctx_list
[0].result
!= 0) {
1285 status
= dcerpc_map_ack_reason(&pkt
->u
.bind_ack
.ctx_list
[0]);
1286 DEBUG(2,("dcerpc: bind_ack failed - reason %d - %s\n",
1287 pkt
->u
.bind_ack
.ctx_list
[0].reason
.value
,
1288 nt_errstr(status
)));
1289 tevent_req_nterror(req
, status
);
1293 if (pkt
->u
.bind_ack
.num_results
>= 2) {
1294 if (pkt
->u
.bind_ack
.ctx_list
[1].result
== DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK
) {
1295 conn
->bind_time_features
= pkt
->u
.bind_ack
.ctx_list
[1].reason
.negotiate
;
1297 status
= dcerpc_map_ack_reason(&pkt
->u
.bind_ack
.ctx_list
[1]);
1298 DEBUG(10,("dcerpc: bind_time_feature failed - reason %d - %s\n",
1299 pkt
->u
.bind_ack
.ctx_list
[1].reason
.value
,
1300 nt_errstr(status
)));
1301 status
= NT_STATUS_OK
;
1306 * DCE-RPC 1.1 (c706) specifies
1307 * CONST_MUST_RCV_FRAG_SIZE as 1432
1309 if (pkt
->u
.bind_ack
.max_xmit_frag
< 1432) {
1310 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
1311 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
1314 if (pkt
->u
.bind_ack
.max_recv_frag
< 1432) {
1315 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
1316 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
1319 conn
->srv_max_xmit_frag
= MIN(conn
->srv_max_xmit_frag
,
1320 pkt
->u
.bind_ack
.max_xmit_frag
);
1321 conn
->srv_max_recv_frag
= MIN(conn
->srv_max_recv_frag
,
1322 pkt
->u
.bind_ack
.max_recv_frag
);
1324 flags
= dcerpc_binding_get_flags(state
->p
->binding
);
1326 if (flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
1327 if (pkt
->pfc_flags
& DCERPC_PFC_FLAG_CONC_MPX
) {
1328 conn
->flags
|= DCERPC_CONCURRENT_MULTIPLEX
;
1330 conn
->flags
&= ~DCERPC_CONCURRENT_MULTIPLEX
;
1334 if (!(conn
->flags
& DCERPC_CONCURRENT_MULTIPLEX
)) {
1335 struct dcerpc_binding
*pb
=
1336 discard_const_p(struct dcerpc_binding
, state
->p
->binding
);
1338 * clear DCERPC_CONCURRENT_MULTIPLEX
1340 status
= dcerpc_binding_set_flags(pb
, 0,
1341 DCERPC_CONCURRENT_MULTIPLEX
);
1342 if (tevent_req_nterror(req
, status
)) {
1346 if ((conn
->flags
& DCERPC_PROPOSE_HEADER_SIGNING
) &&
1347 (pkt
->pfc_flags
& DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
)) {
1348 conn
->flags
|= DCERPC_HEADER_SIGNING
;
1351 /* the bind_ack might contain a reply set of credentials */
1352 if (pkt
->auth_length
!= 0 && sec
->tmp_auth_info
.in
!= NULL
) {
1353 status
= dcerpc_pull_auth_trailer(pkt
, sec
->tmp_auth_info
.mem
,
1354 &pkt
->u
.bind_ack
.auth_info
,
1355 sec
->tmp_auth_info
.in
,
1357 if (tevent_req_nterror(req
, status
)) {
1363 * We're the owner of the binding, so we're allowed to modify it.
1365 b
= discard_const_p(struct dcerpc_binding
, state
->p
->binding
);
1366 status
= dcerpc_binding_set_assoc_group_id(b
,
1367 pkt
->u
.bind_ack
.assoc_group_id
);
1368 if (tevent_req_nterror(req
, status
)) {
1371 status
= dcerpc_binding_set_abstract_syntax(b
, &state
->p
->syntax
);
1372 if (tevent_req_nterror(req
, status
)) {
1376 tevent_req_done(req
);
1379 NTSTATUS
dcerpc_bind_recv(struct tevent_req
*req
)
1381 return tevent_req_simple_recv_ntstatus(req
);
1385 perform a continued bind (and auth3)
1387 NTSTATUS
dcerpc_auth3(struct dcerpc_pipe
*p
,
1388 TALLOC_CTX
*mem_ctx
)
1390 struct ncacn_packet pkt
;
1395 flags
= dcerpc_binding_get_flags(p
->binding
);
1397 init_ncacn_hdr(p
->conn
, &pkt
);
1399 pkt
.ptype
= DCERPC_PKT_AUTH3
;
1400 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
1401 pkt
.call_id
= next_call_id(p
->conn
);
1402 pkt
.auth_length
= 0;
1403 pkt
.u
.auth3
.auth_info
= data_blob(NULL
, 0);
1405 if (flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
1406 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
1409 /* construct the NDR form of the packet */
1410 status
= dcerpc_ncacn_push_auth(&blob
,
1413 p
->conn
->security_state
.tmp_auth_info
.out
);
1414 if (!NT_STATUS_IS_OK(status
)) {
1418 /* send it on its way */
1419 status
= dcerpc_send_request(p
->conn
, &blob
, false);
1420 if (!NT_STATUS_IS_OK(status
)) {
1424 return NT_STATUS_OK
;
1429 process a fragment received from the transport layer during a
1432 This function frees the data
1434 static void dcerpc_request_recv_data(struct dcecli_connection
*c
,
1435 DATA_BLOB
*raw_packet
, struct ncacn_packet
*pkt
)
1437 struct rpc_request
*req
;
1438 unsigned int length
;
1439 NTSTATUS status
= NT_STATUS_OK
;
1442 if this is an authenticated connection then parse and check
1443 the auth info. We have to do this before finding the
1444 matching packet, as the request structure might have been
1445 removed due to a timeout, but if it has been we still need
1446 to run the auth routines so that we don't get the sign/seal
1447 info out of step with the server
1449 switch (pkt
->ptype
) {
1450 case DCERPC_PKT_RESPONSE
:
1451 status
= ncacn_pull_pkt_auth(c
, raw_packet
->data
,
1452 DCERPC_PKT_RESPONSE
,
1453 0, /* required_flags */
1454 DCERPC_PFC_FLAG_FIRST
|
1455 DCERPC_PFC_FLAG_LAST
,
1456 DCERPC_REQUEST_LENGTH
,
1457 &pkt
->u
.response
.stub_and_verifier
,
1464 /* find the matching request */
1465 for (req
=c
->pending
;req
;req
=req
->next
) {
1466 if (pkt
->call_id
== req
->call_id
) break;
1470 /* useful for testing certain vendors RPC servers */
1471 if (req
== NULL
&& c
->pending
&& pkt
->call_id
== 0) {
1472 DEBUG(0,("HACK FOR INCORRECT CALL ID\n"));
1478 DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt
->call_id
));
1479 data_blob_free(raw_packet
);
1483 talloc_steal(req
, raw_packet
->data
);
1485 if (req
->recv_handler
!= NULL
) {
1486 dcerpc_req_dequeue(req
);
1487 req
->state
= RPC_REQUEST_DONE
;
1490 * We have to look at shipping further requests before calling
1491 * the async function, that one might close the pipe
1493 dcerpc_schedule_io_trigger(c
);
1495 req
->recv_handler(req
, raw_packet
, pkt
);
1499 if (pkt
->ptype
== DCERPC_PKT_FAULT
) {
1500 status
= dcerpc_fault_to_nt_status(pkt
->u
.fault
.status
);
1501 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c
, pkt
->u
.fault
.status
)));
1502 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROTOCOL_ERROR
)) {
1503 dcerpc_connection_dead(c
, status
);
1506 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_SEC_PKG_ERROR
)) {
1507 dcerpc_connection_dead(c
, status
);
1510 req
->fault_code
= pkt
->u
.fault
.status
;
1511 req
->status
= NT_STATUS_NET_WRITE_FAULT
;
1515 if (pkt
->ptype
!= DCERPC_PKT_RESPONSE
) {
1516 DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
1518 dcerpc_connection_dead(c
, NT_STATUS_RPC_PROTOCOL_ERROR
);
1522 /* now check the status from the auth routines, and if it failed then fail
1523 this request accordingly */
1524 if (!NT_STATUS_IS_OK(status
)) {
1525 dcerpc_connection_dead(c
, status
);
1529 length
= pkt
->u
.response
.stub_and_verifier
.length
;
1531 if (req
->payload
.length
+ length
> c
->max_total_response_size
) {
1532 DEBUG(2,("Unexpected total payload 0x%X > 0x%X dcerpc response\n",
1533 (unsigned)req
->payload
.length
+ length
,
1534 (unsigned)c
->max_total_response_size
));
1535 dcerpc_connection_dead(c
, NT_STATUS_RPC_PROTOCOL_ERROR
);
1540 req
->payload
.data
= talloc_realloc(req
,
1543 req
->payload
.length
+ length
);
1544 if (!req
->payload
.data
) {
1545 req
->status
= NT_STATUS_NO_MEMORY
;
1548 memcpy(req
->payload
.data
+req
->payload
.length
,
1549 pkt
->u
.response
.stub_and_verifier
.data
, length
);
1550 req
->payload
.length
+= length
;
1553 if (!(pkt
->pfc_flags
& DCERPC_PFC_FLAG_LAST
)) {
1554 data_blob_free(raw_packet
);
1555 dcerpc_send_read(c
);
1559 if (req
->verify_bitmask1
) {
1560 req
->p
->conn
->security_state
.verified_bitmask1
= true;
1562 if (req
->verify_pcontext
) {
1563 req
->p
->verified_pcontext
= true;
1566 if (!(pkt
->drep
[0] & DCERPC_DREP_LE
)) {
1567 req
->flags
|= DCERPC_PULL_BIGENDIAN
;
1569 req
->flags
&= ~DCERPC_PULL_BIGENDIAN
;
1573 data_blob_free(raw_packet
);
1575 /* we've got the full payload */
1576 dcerpc_req_dequeue(req
);
1577 req
->state
= RPC_REQUEST_DONE
;
1580 * We have to look at shipping further requests before calling
1581 * the async function, that one might close the pipe
1583 dcerpc_schedule_io_trigger(c
);
1585 if (req
->async
.callback
) {
1586 req
->async
.callback(req
);
1590 static NTSTATUS
dcerpc_request_prepare_vt(struct rpc_request
*req
);
1593 perform the send side of a async dcerpc request
1595 static struct rpc_request
*dcerpc_request_send(TALLOC_CTX
*mem_ctx
,
1596 struct dcerpc_pipe
*p
,
1597 const struct GUID
*object
,
1599 DATA_BLOB
*stub_data
)
1601 struct rpc_request
*req
;
1604 req
= talloc_zero(mem_ctx
, struct rpc_request
);
1610 req
->call_id
= next_call_id(p
->conn
);
1611 req
->state
= RPC_REQUEST_QUEUED
;
1613 if (object
!= NULL
) {
1614 req
->object
= (struct GUID
*)talloc_memdup(req
, (const void *)object
, sizeof(*object
));
1615 if (req
->object
== NULL
) {
1622 req
->request_data
.length
= stub_data
->length
;
1623 req
->request_data
.data
= stub_data
->data
;
1625 status
= dcerpc_request_prepare_vt(req
);
1626 if (!NT_STATUS_IS_OK(status
)) {
1631 DLIST_ADD_END(p
->conn
->request_queue
, req
);
1632 talloc_set_destructor(req
, dcerpc_req_dequeue
);
1634 dcerpc_schedule_io_trigger(p
->conn
);
1636 if (p
->request_timeout
) {
1637 tevent_add_timer(p
->conn
->event_ctx
, req
,
1638 timeval_current_ofs(p
->request_timeout
, 0),
1639 dcerpc_timeout_handler
, req
);
1645 static NTSTATUS
dcerpc_request_prepare_vt(struct rpc_request
*req
)
1647 struct dcecli_security
*sec
= &req
->p
->conn
->security_state
;
1648 struct dcerpc_sec_verification_trailer
*t
;
1649 struct dcerpc_sec_vt
*c
= NULL
;
1650 struct ndr_push
*ndr
= NULL
;
1651 enum ndr_err_code ndr_err
;
1653 if (sec
->auth_level
< DCERPC_AUTH_LEVEL_PACKET
) {
1654 return NT_STATUS_OK
;
1657 t
= talloc_zero(req
, struct dcerpc_sec_verification_trailer
);
1659 return NT_STATUS_NO_MEMORY
;
1662 if (!sec
->verified_bitmask1
) {
1663 t
->commands
= talloc_realloc(t
, t
->commands
,
1664 struct dcerpc_sec_vt
,
1665 t
->count
.count
+ 1);
1666 if (t
->commands
== NULL
) {
1667 return NT_STATUS_NO_MEMORY
;
1669 c
= &t
->commands
[t
->count
.count
++];
1672 c
->command
= DCERPC_SEC_VT_COMMAND_BITMASK1
;
1673 if (req
->p
->conn
->flags
& DCERPC_PROPOSE_HEADER_SIGNING
) {
1674 c
->u
.bitmask1
= DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING
;
1676 req
->verify_bitmask1
= true;
1679 if (!req
->p
->verified_pcontext
) {
1680 t
->commands
= talloc_realloc(t
, t
->commands
,
1681 struct dcerpc_sec_vt
,
1682 t
->count
.count
+ 1);
1683 if (t
->commands
== NULL
) {
1684 return NT_STATUS_NO_MEMORY
;
1686 c
= &t
->commands
[t
->count
.count
++];
1689 c
->command
= DCERPC_SEC_VT_COMMAND_PCONTEXT
;
1690 c
->u
.pcontext
.abstract_syntax
= req
->p
->syntax
;
1691 c
->u
.pcontext
.transfer_syntax
= req
->p
->transfer_syntax
;
1693 req
->verify_pcontext
= true;
1696 if (!(req
->p
->conn
->flags
& DCERPC_HEADER_SIGNING
)) {
1697 t
->commands
= talloc_realloc(t
, t
->commands
,
1698 struct dcerpc_sec_vt
,
1699 t
->count
.count
+ 1);
1700 if (t
->commands
== NULL
) {
1701 return NT_STATUS_NO_MEMORY
;
1703 c
= &t
->commands
[t
->count
.count
++];
1706 c
->command
= DCERPC_SEC_VT_COMMAND_HEADER2
;
1707 c
->u
.header2
.ptype
= DCERPC_PKT_REQUEST
;
1708 if (req
->p
->conn
->flags
& DCERPC_PUSH_BIGENDIAN
) {
1709 c
->u
.header2
.drep
[0] = 0;
1711 c
->u
.header2
.drep
[0] = DCERPC_DREP_LE
;
1713 c
->u
.header2
.drep
[1] = 0;
1714 c
->u
.header2
.drep
[2] = 0;
1715 c
->u
.header2
.drep
[3] = 0;
1716 c
->u
.header2
.call_id
= req
->call_id
;
1717 c
->u
.header2
.context_id
= req
->p
->context_id
;
1718 c
->u
.header2
.opnum
= req
->opnum
;
1721 if (t
->count
.count
== 0) {
1723 return NT_STATUS_OK
;
1726 c
= &t
->commands
[t
->count
.count
- 1];
1727 c
->command
|= DCERPC_SEC_VT_COMMAND_END
;
1729 if (DEBUGLEVEL
>= 10) {
1730 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer
, t
);
1733 ndr
= ndr_push_init_ctx(req
);
1735 return NT_STATUS_NO_MEMORY
;
1739 * for now we just copy and append
1742 ndr_err
= ndr_push_bytes(ndr
, req
->request_data
.data
,
1743 req
->request_data
.length
);
1744 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1745 return ndr_map_error2ntstatus(ndr_err
);
1748 ndr_err
= ndr_push_dcerpc_sec_verification_trailer(ndr
,
1749 NDR_SCALARS
| NDR_BUFFERS
,
1751 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1752 return ndr_map_error2ntstatus(ndr_err
);
1754 req
->request_data
= ndr_push_blob(ndr
);
1756 return NT_STATUS_OK
;
1760 Send a request using the transport
1763 static void dcerpc_ship_next_request(struct dcecli_connection
*c
)
1765 struct rpc_request
*req
;
1766 struct dcerpc_pipe
*p
;
1767 DATA_BLOB
*stub_data
;
1768 struct ncacn_packet pkt
;
1770 uint32_t remaining
, chunk_size
;
1771 bool first_packet
= true;
1772 size_t sig_size
= 0;
1773 bool need_async
= false;
1774 bool can_async
= true;
1776 req
= c
->request_queue
;
1782 stub_data
= &req
->request_data
;
1788 if (c
->security_state
.auth_level
>= DCERPC_AUTH_LEVEL_PACKET
) {
1789 can_async
= gensec_have_feature(c
->security_state
.generic_state
,
1790 GENSEC_FEATURE_ASYNC_REPLIES
);
1793 if (need_async
&& !can_async
) {
1794 req
->wait_for_sync
= true;
1798 DLIST_REMOVE(c
->request_queue
, req
);
1799 DLIST_ADD(c
->pending
, req
);
1800 req
->state
= RPC_REQUEST_PENDING
;
1802 init_ncacn_hdr(p
->conn
, &pkt
);
1804 remaining
= stub_data
->length
;
1806 /* we can write a full max_recv_frag size, minus the dcerpc
1807 request header size */
1808 chunk_size
= p
->conn
->srv_max_recv_frag
;
1809 chunk_size
-= DCERPC_REQUEST_LENGTH
;
1810 if (c
->security_state
.auth_level
>= DCERPC_AUTH_LEVEL_PACKET
) {
1811 size_t max_payload
= chunk_size
;
1813 max_payload
-= DCERPC_AUTH_TRAILER_LENGTH
;
1814 max_payload
-= (max_payload
% DCERPC_AUTH_PAD_ALIGNMENT
);
1816 sig_size
= gensec_sig_size(c
->security_state
.generic_state
,
1819 chunk_size
-= DCERPC_AUTH_TRAILER_LENGTH
;
1820 chunk_size
-= sig_size
;
1823 chunk_size
-= (chunk_size
% DCERPC_AUTH_PAD_ALIGNMENT
);
1825 pkt
.ptype
= DCERPC_PKT_REQUEST
;
1826 pkt
.call_id
= req
->call_id
;
1827 pkt
.auth_length
= 0;
1829 pkt
.u
.request
.context_id
= p
->context_id
;
1830 pkt
.u
.request
.opnum
= req
->opnum
;
1833 pkt
.u
.request
.object
.object
= *req
->object
;
1834 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_OBJECT_UUID
;
1835 chunk_size
-= ndr_size_GUID(req
->object
,0);
1838 /* we send a series of pdus without waiting for a reply */
1839 while (remaining
> 0 || first_packet
) {
1840 uint32_t chunk
= MIN(chunk_size
, remaining
);
1841 bool last_frag
= false;
1842 bool do_trans
= false;
1844 first_packet
= false;
1845 pkt
.pfc_flags
&= ~(DCERPC_PFC_FLAG_FIRST
|DCERPC_PFC_FLAG_LAST
);
1847 if (remaining
== stub_data
->length
) {
1848 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_FIRST
;
1850 if (chunk
== remaining
) {
1851 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_LAST
;
1855 pkt
.u
.request
.alloc_hint
= remaining
;
1856 pkt
.u
.request
.stub_and_verifier
.data
= stub_data
->data
+
1857 (stub_data
->length
- remaining
);
1858 pkt
.u
.request
.stub_and_verifier
.length
= chunk
;
1860 req
->status
= ncacn_push_request_sign(p
->conn
, &blob
, req
, sig_size
, &pkt
);
1861 if (!NT_STATUS_IS_OK(req
->status
)) {
1862 req
->state
= RPC_REQUEST_DONE
;
1863 DLIST_REMOVE(p
->conn
->pending
, req
);
1867 if (last_frag
&& !need_async
) {
1871 req
->status
= dcerpc_send_request(p
->conn
, &blob
, do_trans
);
1872 if (!NT_STATUS_IS_OK(req
->status
)) {
1873 req
->state
= RPC_REQUEST_DONE
;
1874 DLIST_REMOVE(p
->conn
->pending
, req
);
1878 if (last_frag
&& !do_trans
) {
1879 req
->status
= dcerpc_send_read(p
->conn
);
1880 if (!NT_STATUS_IS_OK(req
->status
)) {
1881 req
->state
= RPC_REQUEST_DONE
;
1882 DLIST_REMOVE(p
->conn
->pending
, req
);
1891 static void dcerpc_io_trigger(struct tevent_context
*ctx
,
1892 struct tevent_immediate
*im
,
1895 struct dcecli_connection
*c
=
1896 talloc_get_type_abort(private_data
,
1897 struct dcecli_connection
);
1899 c
->io_trigger_pending
= false;
1901 dcerpc_schedule_io_trigger(c
);
1903 dcerpc_ship_next_request(c
);
1906 static void dcerpc_schedule_io_trigger(struct dcecli_connection
*c
)
1912 if (c
->request_queue
== NULL
) {
1916 if (c
->request_queue
->wait_for_sync
&& c
->pending
) {
1920 if (c
->io_trigger_pending
) {
1924 c
->io_trigger_pending
= true;
1926 tevent_schedule_immediate(c
->io_trigger
,
1933 perform the receive side of a async dcerpc request
1935 static NTSTATUS
dcerpc_request_recv(struct rpc_request
*req
,
1936 TALLOC_CTX
*mem_ctx
,
1937 DATA_BLOB
*stub_data
)
1941 while (req
->state
!= RPC_REQUEST_DONE
) {
1942 struct tevent_context
*ctx
= req
->p
->conn
->event_ctx
;
1943 if (tevent_loop_once(ctx
) != 0) {
1944 return NT_STATUS_CONNECTION_DISCONNECTED
;
1947 *stub_data
= req
->payload
;
1948 status
= req
->status
;
1949 if (stub_data
->data
) {
1950 stub_data
->data
= talloc_steal(mem_ctx
, stub_data
->data
);
1952 if (NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
1953 req
->p
->last_fault_code
= req
->fault_code
;
1955 talloc_unlink(talloc_parent(req
), req
);
1960 this is a paranoid NDR validator. For every packet we push onto the wire
1961 we pull it back again, then push it again. Then we compare the raw NDR data
1962 for that to the NDR we initially generated. If they don't match then we know
1963 we must have a bug in either the pull or push side of our code
1965 static NTSTATUS
dcerpc_ndr_validate_in(struct dcecli_connection
*c
,
1966 TALLOC_CTX
*mem_ctx
,
1969 ndr_push_flags_fn_t ndr_push
,
1970 ndr_pull_flags_fn_t ndr_pull
)
1973 struct ndr_pull
*pull
;
1974 struct ndr_push
*push
;
1976 enum ndr_err_code ndr_err
;
1978 st
= talloc_size(mem_ctx
, struct_size
);
1980 return NT_STATUS_NO_MEMORY
;
1983 pull
= ndr_pull_init_flags(c
, &blob
, mem_ctx
);
1985 return NT_STATUS_NO_MEMORY
;
1987 pull
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
1989 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
1990 pull
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
1993 if (c
->flags
& DCERPC_NDR64
) {
1994 pull
->flags
|= LIBNDR_FLAG_NDR64
;
1997 ndr_err
= ndr_pull(pull
, NDR_IN
, st
);
1998 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1999 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
2000 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
2001 "failed input validation pull - %s",
2003 return ndr_map_error2ntstatus(ndr_err
);
2006 push
= ndr_push_init_ctx(mem_ctx
);
2008 return NT_STATUS_NO_MEMORY
;
2011 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
2012 push
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
2015 if (c
->flags
& DCERPC_NDR64
) {
2016 push
->flags
|= LIBNDR_FLAG_NDR64
;
2019 ndr_err
= ndr_push(push
, NDR_IN
, st
);
2020 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2021 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
2022 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
2023 "failed input validation push - %s",
2025 return ndr_map_error2ntstatus(ndr_err
);
2028 blob2
= ndr_push_blob(push
);
2030 if (data_blob_cmp(&blob
, &blob2
) != 0) {
2031 DEBUG(3,("original:\n"));
2032 dump_data(3, blob
.data
, blob
.length
);
2033 DEBUG(3,("secondary:\n"));
2034 dump_data(3, blob2
.data
, blob2
.length
);
2035 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
2036 "failed input validation blobs doesn't match");
2037 return ndr_map_error2ntstatus(ndr_err
);
2040 return NT_STATUS_OK
;
2044 this is a paranoid NDR input validator. For every packet we pull
2045 from the wire we push it back again then pull and push it
2046 again. Then we compare the raw NDR data for that to the NDR we
2047 initially generated. If they don't match then we know we must have a
2048 bug in either the pull or push side of our code
2050 static NTSTATUS
dcerpc_ndr_validate_out(struct dcecli_connection
*c
,
2051 struct ndr_pull
*pull_in
,
2054 ndr_push_flags_fn_t ndr_push
,
2055 ndr_pull_flags_fn_t ndr_pull
,
2056 ndr_print_function_t ndr_print
)
2059 struct ndr_pull
*pull
;
2060 struct ndr_push
*push
;
2061 DATA_BLOB blob
, blob2
;
2062 TALLOC_CTX
*mem_ctx
= pull_in
;
2064 enum ndr_err_code ndr_err
;
2066 st
= talloc_size(mem_ctx
, struct_size
);
2068 return NT_STATUS_NO_MEMORY
;
2070 memcpy(st
, struct_ptr
, struct_size
);
2072 push
= ndr_push_init_ctx(mem_ctx
);
2074 return NT_STATUS_NO_MEMORY
;
2077 ndr_err
= ndr_push(push
, NDR_OUT
, struct_ptr
);
2078 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2079 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
2080 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
2081 "failed output validation push - %s",
2083 return ndr_map_error2ntstatus(ndr_err
);
2086 blob
= ndr_push_blob(push
);
2088 pull
= ndr_pull_init_flags(c
, &blob
, mem_ctx
);
2090 return NT_STATUS_NO_MEMORY
;
2093 pull
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
2094 ndr_err
= ndr_pull(pull
, NDR_OUT
, st
);
2095 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2096 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
2097 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
2098 "failed output validation pull - %s",
2100 return ndr_map_error2ntstatus(ndr_err
);
2103 push
= ndr_push_init_ctx(mem_ctx
);
2105 return NT_STATUS_NO_MEMORY
;
2108 ndr_err
= ndr_push(push
, NDR_OUT
, st
);
2109 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2110 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
2111 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
2112 "failed output validation push2 - %s",
2114 return ndr_map_error2ntstatus(ndr_err
);
2117 blob2
= ndr_push_blob(push
);
2119 if (data_blob_cmp(&blob
, &blob2
) != 0) {
2120 DEBUG(3,("original:\n"));
2121 dump_data(3, blob
.data
, blob
.length
);
2122 DEBUG(3,("secondary:\n"));
2123 dump_data(3, blob2
.data
, blob2
.length
);
2124 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
2125 "failed output validation blobs doesn't match");
2126 return ndr_map_error2ntstatus(ndr_err
);
2129 /* this checks the printed forms of the two structures, which effectively
2130 tests all of the value() attributes */
2131 s1
= ndr_print_function_string(mem_ctx
, ndr_print
, "VALIDATE",
2132 NDR_OUT
, struct_ptr
);
2133 s2
= ndr_print_function_string(mem_ctx
, ndr_print
, "VALIDATE",
2135 if (strcmp(s1
, s2
) != 0) {
2137 DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1
, s2
));
2139 /* this is sometimes useful */
2140 printf("VALIDATE ERROR\n");
2141 file_save("wire.dat", s1
, strlen(s1
));
2142 file_save("gen.dat", s2
, strlen(s2
));
2143 system("diff -u wire.dat gen.dat");
2145 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
2146 "failed output validation strings doesn't match");
2147 return ndr_map_error2ntstatus(ndr_err
);
2150 return NT_STATUS_OK
;
2154 a useful function for retrieving the server name we connected to
2156 _PUBLIC_
const char *dcerpc_server_name(struct dcerpc_pipe
*p
)
2158 return p
->conn
? p
->conn
->server_name
: NULL
;
2163 get the dcerpc auth_level for a open connection
2165 uint32_t dcerpc_auth_level(struct dcecli_connection
*c
)
2169 if (c
->flags
& DCERPC_SEAL
) {
2170 auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
2171 } else if (c
->flags
& DCERPC_SIGN
) {
2172 auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
2173 } else if (c
->flags
& DCERPC_PACKET
) {
2174 auth_level
= DCERPC_AUTH_LEVEL_PACKET
;
2175 } else if (c
->flags
& DCERPC_CONNECT
) {
2176 auth_level
= DCERPC_AUTH_LEVEL_CONNECT
;
2178 auth_level
= DCERPC_AUTH_LEVEL_NONE
;
2183 struct dcerpc_alter_context_state
{
2184 struct tevent_context
*ev
;
2185 struct dcerpc_pipe
*p
;
2188 static void dcerpc_alter_context_fail_handler(struct rpc_request
*subreq
);
2189 static void dcerpc_alter_context_recv_handler(struct rpc_request
*req
,
2190 DATA_BLOB
*raw_packet
,
2191 struct ncacn_packet
*pkt
);
2193 struct tevent_req
*dcerpc_alter_context_send(TALLOC_CTX
*mem_ctx
,
2194 struct tevent_context
*ev
,
2195 struct dcerpc_pipe
*p
,
2196 const struct ndr_syntax_id
*syntax
,
2197 const struct ndr_syntax_id
*transfer_syntax
)
2199 struct tevent_req
*req
;
2200 struct dcerpc_alter_context_state
*state
;
2201 struct ncacn_packet pkt
;
2204 struct rpc_request
*subreq
;
2207 req
= tevent_req_create(mem_ctx
, &state
,
2208 struct dcerpc_alter_context_state
);
2216 p
->syntax
= *syntax
;
2217 p
->transfer_syntax
= *transfer_syntax
;
2219 flags
= dcerpc_binding_get_flags(p
->binding
);
2221 init_ncacn_hdr(p
->conn
, &pkt
);
2223 pkt
.ptype
= DCERPC_PKT_ALTER
;
2224 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
2225 pkt
.call_id
= p
->conn
->call_id
;
2226 pkt
.auth_length
= 0;
2228 if (flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
2229 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
2232 pkt
.u
.alter
.max_xmit_frag
= p
->conn
->srv_max_xmit_frag
;
2233 pkt
.u
.alter
.max_recv_frag
= p
->conn
->srv_max_recv_frag
;
2234 pkt
.u
.alter
.assoc_group_id
= dcerpc_binding_get_assoc_group_id(p
->binding
);
2235 pkt
.u
.alter
.num_contexts
= 1;
2236 pkt
.u
.alter
.ctx_list
= talloc_zero_array(state
, struct dcerpc_ctx_list
,
2237 pkt
.u
.alter
.num_contexts
);
2238 if (tevent_req_nomem(pkt
.u
.alter
.ctx_list
, req
)) {
2239 return tevent_req_post(req
, ev
);
2241 pkt
.u
.alter
.ctx_list
[0].context_id
= p
->context_id
;
2242 pkt
.u
.alter
.ctx_list
[0].num_transfer_syntaxes
= 1;
2243 pkt
.u
.alter
.ctx_list
[0].abstract_syntax
= p
->syntax
;
2244 pkt
.u
.alter
.ctx_list
[0].transfer_syntaxes
= &p
->transfer_syntax
;
2245 pkt
.u
.alter
.auth_info
= data_blob(NULL
, 0);
2247 /* construct the NDR form of the packet */
2248 status
= dcerpc_ncacn_push_auth(&blob
,
2251 p
->conn
->security_state
.tmp_auth_info
.out
);
2252 if (tevent_req_nterror(req
, status
)) {
2253 return tevent_req_post(req
, ev
);
2257 * we allocate a dcerpc_request so we can be in the same
2258 * request queue as normal requests
2260 subreq
= talloc_zero(state
, struct rpc_request
);
2261 if (tevent_req_nomem(subreq
, req
)) {
2262 return tevent_req_post(req
, ev
);
2265 subreq
->state
= RPC_REQUEST_PENDING
;
2266 subreq
->call_id
= pkt
.call_id
;
2267 subreq
->async
.private_data
= req
;
2268 subreq
->async
.callback
= dcerpc_alter_context_fail_handler
;
2270 subreq
->recv_handler
= dcerpc_alter_context_recv_handler
;
2271 DLIST_ADD_END(p
->conn
->pending
, subreq
);
2272 talloc_set_destructor(subreq
, dcerpc_req_dequeue
);
2274 status
= dcerpc_send_request(p
->conn
, &blob
, true);
2275 if (tevent_req_nterror(req
, status
)) {
2276 return tevent_req_post(req
, ev
);
2279 tevent_add_timer(ev
, subreq
,
2280 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT
, 0),
2281 dcerpc_timeout_handler
, subreq
);
2286 static void dcerpc_alter_context_fail_handler(struct rpc_request
*subreq
)
2288 struct tevent_req
*req
=
2289 talloc_get_type_abort(subreq
->async
.private_data
,
2291 struct dcerpc_alter_context_state
*state
=
2292 tevent_req_data(req
,
2293 struct dcerpc_alter_context_state
);
2294 NTSTATUS status
= subreq
->status
;
2296 TALLOC_FREE(subreq
);
2299 * We trigger the callback in the next event run
2300 * because the code in this file might trigger
2301 * multiple request callbacks from within a single
2304 * In order to avoid segfaults from within
2305 * dcerpc_connection_dead() we call
2306 * tevent_req_defer_callback().
2308 tevent_req_defer_callback(req
, state
->ev
);
2310 tevent_req_nterror(req
, status
);
2313 static void dcerpc_alter_context_recv_handler(struct rpc_request
*subreq
,
2314 DATA_BLOB
*raw_packet
,
2315 struct ncacn_packet
*pkt
)
2317 struct tevent_req
*req
=
2318 talloc_get_type_abort(subreq
->async
.private_data
,
2320 struct dcerpc_alter_context_state
*state
=
2321 tevent_req_data(req
,
2322 struct dcerpc_alter_context_state
);
2323 struct dcecli_connection
*conn
= state
->p
->conn
;
2324 struct dcecli_security
*sec
= &conn
->security_state
;
2325 struct dcerpc_binding
*b
= NULL
;
2329 * Note that pkt is allocated under raw_packet->data,
2330 * while raw_packet->data is a child of subreq.
2332 talloc_steal(state
, raw_packet
->data
);
2333 TALLOC_FREE(subreq
);
2336 * We trigger the callback in the next event run
2337 * because the code in this file might trigger
2338 * multiple request callbacks from within a single
2341 * In order to avoid segfaults from within
2342 * dcerpc_connection_dead() we call
2343 * tevent_req_defer_callback().
2345 tevent_req_defer_callback(req
, state
->ev
);
2347 if (pkt
->ptype
== DCERPC_PKT_FAULT
) {
2348 DEBUG(5,("dcerpc: alter_resp - rpc fault: %s\n",
2349 dcerpc_errstr(state
, pkt
->u
.fault
.status
)));
2350 if (pkt
->u
.fault
.status
== DCERPC_FAULT_ACCESS_DENIED
) {
2351 state
->p
->last_fault_code
= pkt
->u
.fault
.status
;
2352 tevent_req_nterror(req
, NT_STATUS_LOGON_FAILURE
);
2353 } else if (pkt
->u
.fault
.status
== DCERPC_FAULT_SEC_PKG_ERROR
) {
2354 state
->p
->last_fault_code
= pkt
->u
.fault
.status
;
2355 tevent_req_nterror(req
, NT_STATUS_LOGON_FAILURE
);
2357 state
->p
->last_fault_code
= pkt
->u
.fault
.status
;
2358 status
= dcerpc_fault_to_nt_status(pkt
->u
.fault
.status
);
2359 tevent_req_nterror(req
, status
);
2364 status
= dcerpc_verify_ncacn_packet_header(pkt
,
2365 DCERPC_PKT_ALTER_RESP
,
2366 pkt
->u
.alter_resp
.auth_info
.length
,
2367 DCERPC_PFC_FLAG_FIRST
|
2368 DCERPC_PFC_FLAG_LAST
,
2369 DCERPC_PFC_FLAG_CONC_MPX
|
2370 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
);
2371 if (!NT_STATUS_IS_OK(status
)) {
2372 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
2373 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
2377 if (pkt
->u
.alter_resp
.num_results
!= 1) {
2378 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
2379 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
2383 if (pkt
->u
.alter_resp
.ctx_list
[0].result
!= 0) {
2384 status
= dcerpc_map_ack_reason(&pkt
->u
.alter_resp
.ctx_list
[0]);
2385 DEBUG(2,("dcerpc: alter_resp failed - reason %d - %s\n",
2386 pkt
->u
.alter_resp
.ctx_list
[0].reason
.value
,
2387 nt_errstr(status
)));
2388 tevent_req_nterror(req
, status
);
2392 /* the alter_resp might contain a reply set of credentials */
2393 if (pkt
->auth_length
!= 0 && sec
->tmp_auth_info
.in
!= NULL
) {
2394 status
= dcerpc_pull_auth_trailer(pkt
, sec
->tmp_auth_info
.mem
,
2395 &pkt
->u
.alter_resp
.auth_info
,
2396 sec
->tmp_auth_info
.in
,
2398 if (tevent_req_nterror(req
, status
)) {
2404 * We're the owner of the binding, so we're allowed to modify it.
2406 b
= discard_const_p(struct dcerpc_binding
, state
->p
->binding
);
2407 status
= dcerpc_binding_set_abstract_syntax(b
, &state
->p
->syntax
);
2408 if (tevent_req_nterror(req
, status
)) {
2412 tevent_req_done(req
);
2415 NTSTATUS
dcerpc_alter_context_recv(struct tevent_req
*req
)
2417 return tevent_req_simple_recv_ntstatus(req
);
2421 send a dcerpc alter_context request
2423 _PUBLIC_ NTSTATUS
dcerpc_alter_context(struct dcerpc_pipe
*p
,
2424 TALLOC_CTX
*mem_ctx
,
2425 const struct ndr_syntax_id
*syntax
,
2426 const struct ndr_syntax_id
*transfer_syntax
)
2428 struct tevent_req
*subreq
;
2429 struct tevent_context
*ev
= p
->conn
->event_ctx
;
2432 /* TODO: create a new event context here */
2434 subreq
= dcerpc_alter_context_send(mem_ctx
, ev
,
2435 p
, syntax
, transfer_syntax
);
2436 if (subreq
== NULL
) {
2437 return NT_STATUS_NO_MEMORY
;
2440 ok
= tevent_req_poll(subreq
, ev
);
2443 status
= map_nt_error_from_unix_common(errno
);
2447 return dcerpc_alter_context_recv(subreq
);
2450 static void dcerpc_transport_dead(struct dcecli_connection
*c
, NTSTATUS status
)
2452 if (c
->transport
.stream
== NULL
) {
2456 tevent_queue_stop(c
->transport
.write_queue
);
2457 TALLOC_FREE(c
->transport
.read_subreq
);
2458 TALLOC_FREE(c
->transport
.stream
);
2460 if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL
, status
)) {
2461 status
= NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
2464 if (NT_STATUS_EQUAL(NT_STATUS_OK
, status
)) {
2465 status
= NT_STATUS_END_OF_FILE
;
2468 dcerpc_recv_data(c
, NULL
, status
);
2473 shutdown SMB pipe connection
2475 struct dcerpc_shutdown_pipe_state
{
2476 struct dcecli_connection
*c
;
2480 static void dcerpc_shutdown_pipe_done(struct tevent_req
*subreq
);
2482 static NTSTATUS
dcerpc_shutdown_pipe(struct dcecli_connection
*c
, NTSTATUS status
)
2484 struct dcerpc_shutdown_pipe_state
*state
;
2485 struct tevent_req
*subreq
;
2487 if (c
->transport
.stream
== NULL
) {
2488 return NT_STATUS_OK
;
2491 state
= talloc_zero(c
, struct dcerpc_shutdown_pipe_state
);
2492 if (state
== NULL
) {
2493 return NT_STATUS_NO_MEMORY
;
2496 state
->status
= status
;
2498 subreq
= tstream_disconnect_send(state
, c
->event_ctx
, c
->transport
.stream
);
2499 if (subreq
== NULL
) {
2500 return NT_STATUS_NO_MEMORY
;
2502 tevent_req_set_callback(subreq
, dcerpc_shutdown_pipe_done
, state
);
2507 static void dcerpc_shutdown_pipe_done(struct tevent_req
*subreq
)
2509 struct dcerpc_shutdown_pipe_state
*state
=
2510 tevent_req_callback_data(subreq
, struct dcerpc_shutdown_pipe_state
);
2511 struct dcecli_connection
*c
= state
->c
;
2512 NTSTATUS status
= state
->status
;
2516 * here we ignore the return values...
2518 tstream_disconnect_recv(subreq
, &error
);
2519 TALLOC_FREE(subreq
);
2523 dcerpc_transport_dead(c
, status
);
2528 struct dcerpc_send_read_state
{
2529 struct dcecli_connection
*p
;
2532 static int dcerpc_send_read_state_destructor(struct dcerpc_send_read_state
*state
)
2534 struct dcecli_connection
*p
= state
->p
;
2536 p
->transport
.read_subreq
= NULL
;
2541 static void dcerpc_send_read_done(struct tevent_req
*subreq
);
2543 static NTSTATUS
dcerpc_send_read(struct dcecli_connection
*p
)
2545 struct dcerpc_send_read_state
*state
;
2547 if (p
->transport
.read_subreq
!= NULL
) {
2548 p
->transport
.pending_reads
++;
2549 return NT_STATUS_OK
;
2552 state
= talloc_zero(p
, struct dcerpc_send_read_state
);
2553 if (state
== NULL
) {
2554 return NT_STATUS_NO_MEMORY
;
2558 talloc_set_destructor(state
, dcerpc_send_read_state_destructor
);
2560 p
->transport
.read_subreq
= dcerpc_read_ncacn_packet_send(state
,
2562 p
->transport
.stream
);
2563 if (p
->transport
.read_subreq
== NULL
) {
2564 return NT_STATUS_NO_MEMORY
;
2566 tevent_req_set_callback(p
->transport
.read_subreq
, dcerpc_send_read_done
, state
);
2568 return NT_STATUS_OK
;
2571 static void dcerpc_send_read_done(struct tevent_req
*subreq
)
2573 struct dcerpc_send_read_state
*state
=
2574 tevent_req_callback_data(subreq
,
2575 struct dcerpc_send_read_state
);
2576 struct dcecli_connection
*p
= state
->p
;
2578 struct ncacn_packet
*pkt
;
2581 status
= dcerpc_read_ncacn_packet_recv(subreq
, state
,
2583 TALLOC_FREE(subreq
);
2584 if (!NT_STATUS_IS_OK(status
)) {
2586 dcerpc_transport_dead(p
, status
);
2591 * here we steal into thet connection context,
2592 * but p->transport.recv_data() will steal or free it again
2594 talloc_steal(p
, blob
.data
);
2597 if (p
->transport
.pending_reads
> 0) {
2598 p
->transport
.pending_reads
--;
2600 status
= dcerpc_send_read(p
);
2601 if (!NT_STATUS_IS_OK(status
)) {
2602 dcerpc_transport_dead(p
, status
);
2607 dcerpc_recv_data(p
, &blob
, NT_STATUS_OK
);
2610 struct dcerpc_send_request_state
{
2611 struct dcecli_connection
*p
;
2616 static int dcerpc_send_request_state_destructor(struct dcerpc_send_request_state
*state
)
2618 struct dcecli_connection
*p
= state
->p
;
2620 p
->transport
.read_subreq
= NULL
;
2625 static void dcerpc_send_request_wait_done(struct tevent_req
*subreq
);
2626 static void dcerpc_send_request_done(struct tevent_req
*subreq
);
2628 static NTSTATUS
dcerpc_send_request(struct dcecli_connection
*p
, DATA_BLOB
*data
,
2631 struct dcerpc_send_request_state
*state
;
2632 struct tevent_req
*subreq
;
2633 bool use_trans
= trigger_read
;
2635 if (p
->transport
.stream
== NULL
) {
2636 return NT_STATUS_CONNECTION_DISCONNECTED
;
2639 state
= talloc_zero(p
, struct dcerpc_send_request_state
);
2640 if (state
== NULL
) {
2641 return NT_STATUS_NO_MEMORY
;
2645 state
->blob
= data_blob_talloc(state
, data
->data
, data
->length
);
2646 if (state
->blob
.data
== NULL
) {
2648 return NT_STATUS_NO_MEMORY
;
2650 state
->iov
.iov_base
= (void *)state
->blob
.data
;
2651 state
->iov
.iov_len
= state
->blob
.length
;
2653 if (p
->transport
.read_subreq
!= NULL
) {
2657 if (!tstream_is_smbXcli_np(p
->transport
.stream
)) {
2663 * we need to block reads until our write is
2664 * the next in the write queue.
2666 p
->transport
.read_subreq
= tevent_queue_wait_send(state
, p
->event_ctx
,
2667 p
->transport
.write_queue
);
2668 if (p
->transport
.read_subreq
== NULL
) {
2670 return NT_STATUS_NO_MEMORY
;
2672 tevent_req_set_callback(p
->transport
.read_subreq
,
2673 dcerpc_send_request_wait_done
,
2676 talloc_set_destructor(state
, dcerpc_send_request_state_destructor
);
2678 trigger_read
= false;
2681 subreq
= tstream_writev_queue_send(state
, p
->event_ctx
,
2682 p
->transport
.stream
,
2683 p
->transport
.write_queue
,
2685 if (subreq
== NULL
) {
2687 return NT_STATUS_NO_MEMORY
;
2689 tevent_req_set_callback(subreq
, dcerpc_send_request_done
, state
);
2692 dcerpc_send_read(p
);
2695 return NT_STATUS_OK
;
2698 static void dcerpc_send_request_wait_done(struct tevent_req
*subreq
)
2700 struct dcerpc_send_request_state
*state
=
2701 tevent_req_callback_data(subreq
,
2702 struct dcerpc_send_request_state
);
2703 struct dcecli_connection
*p
= state
->p
;
2707 p
->transport
.read_subreq
= NULL
;
2708 talloc_set_destructor(state
, NULL
);
2710 ok
= tevent_queue_wait_recv(subreq
);
2713 dcerpc_transport_dead(p
, NT_STATUS_NO_MEMORY
);
2717 if (tevent_queue_length(p
->transport
.write_queue
) <= 2) {
2718 status
= tstream_smbXcli_np_use_trans(p
->transport
.stream
);
2719 if (!NT_STATUS_IS_OK(status
)) {
2721 dcerpc_transport_dead(p
, status
);
2726 /* we free subreq after tstream_cli_np_use_trans */
2727 TALLOC_FREE(subreq
);
2729 dcerpc_send_read(p
);
2732 static void dcerpc_send_request_done(struct tevent_req
*subreq
)
2734 struct dcerpc_send_request_state
*state
=
2735 tevent_req_callback_data(subreq
,
2736 struct dcerpc_send_request_state
);
2740 ret
= tstream_writev_queue_recv(subreq
, &error
);
2741 TALLOC_FREE(subreq
);
2743 struct dcecli_connection
*p
= state
->p
;
2744 NTSTATUS status
= map_nt_error_from_unix_common(error
);
2747 dcerpc_transport_dead(p
, status
);