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 "system/filesys.h"
25 #include "../lib/util/dlinklist.h"
26 #include "lib/events/events.h"
27 #include "librpc/rpc/dcerpc.h"
28 #include "librpc/rpc/dcerpc_proto.h"
29 #include "librpc/gen_ndr/ndr_misc.h"
30 #include "librpc/gen_ndr/ndr_dcerpc.h"
31 #include "auth/gensec/gensec.h"
32 #include "param/param.h"
33 #include "lib/util/tevent_ntstatus.h"
34 #include "librpc/rpc/rpc_common.h"
35 #include "lib/tsocket/tsocket.h"
36 #include "libcli/smb/tstream_smbXcli_np.h"
39 enum rpc_request_state
{
46 handle for an async dcerpc request
49 struct rpc_request
*next
, *prev
;
50 struct dcerpc_pipe
*p
;
53 enum rpc_request_state state
;
58 /* this is used to distinguish bind and alter_context requests
59 from normal requests */
60 void (*recv_handler
)(struct rpc_request
*conn
,
61 DATA_BLOB
*blob
, struct ncacn_packet
*pkt
);
63 const struct GUID
*object
;
65 DATA_BLOB request_data
;
72 void (*callback
)(struct rpc_request
*);
77 _PUBLIC_ NTSTATUS
dcerpc_init(void)
82 static void dcerpc_connection_dead(struct dcecli_connection
*conn
, NTSTATUS status
);
83 static void dcerpc_schedule_io_trigger(struct dcecli_connection
*c
);
85 static struct rpc_request
*dcerpc_request_send(TALLOC_CTX
*mem_ctx
,
86 struct dcerpc_pipe
*p
,
87 const struct GUID
*object
,
89 DATA_BLOB
*stub_data
);
90 static NTSTATUS
dcerpc_request_recv(struct rpc_request
*req
,
92 DATA_BLOB
*stub_data
);
93 static NTSTATUS
dcerpc_ndr_validate_in(struct dcecli_connection
*c
,
97 ndr_push_flags_fn_t ndr_push
,
98 ndr_pull_flags_fn_t ndr_pull
);
99 static NTSTATUS
dcerpc_ndr_validate_out(struct dcecli_connection
*c
,
100 struct ndr_pull
*pull_in
,
103 ndr_push_flags_fn_t ndr_push
,
104 ndr_pull_flags_fn_t ndr_pull
,
105 ndr_print_function_t ndr_print
);
106 static NTSTATUS
dcerpc_shutdown_pipe(struct dcecli_connection
*p
, NTSTATUS status
);
107 static NTSTATUS
dcerpc_send_request(struct dcecli_connection
*p
, DATA_BLOB
*data
,
109 static NTSTATUS
dcerpc_send_read(struct dcecli_connection
*p
);
111 /* destroy a dcerpc connection */
112 static int dcerpc_connection_destructor(struct dcecli_connection
*conn
)
115 conn
->free_skipped
= true;
118 dcerpc_connection_dead(conn
, NT_STATUS_LOCAL_DISCONNECT
);
123 /* initialise a dcerpc connection.
124 the event context is optional
126 static struct dcecli_connection
*dcerpc_connection_init(TALLOC_CTX
*mem_ctx
,
127 struct tevent_context
*ev
)
129 struct dcecli_connection
*c
;
131 c
= talloc_zero(mem_ctx
, struct dcecli_connection
);
138 if (c
->event_ctx
== NULL
) {
144 c
->security_state
.auth_type
= DCERPC_AUTH_TYPE_NONE
;
145 c
->security_state
.auth_level
= DCERPC_AUTH_LEVEL_NONE
;
146 c
->security_state
.auth_context_id
= 0;
147 c
->security_state
.auth_info
= NULL
;
148 c
->security_state
.session_key
= dcerpc_generic_session_key
;
149 c
->security_state
.generic_state
= NULL
;
152 * Windows uses 5840 for ncacn_ip_tcp,
153 * so we also use it (for every transport)
154 * by default. But we give the transport
155 * the chance to overwrite it.
157 c
->srv_max_xmit_frag
= 5840;
158 c
->srv_max_recv_frag
= 5840;
161 c
->io_trigger
= tevent_create_immediate(c
);
162 if (c
->io_trigger
== NULL
) {
167 talloc_set_destructor(c
, dcerpc_connection_destructor
);
172 struct dcerpc_bh_state
{
173 struct dcerpc_pipe
*p
;
176 static bool dcerpc_bh_is_connected(struct dcerpc_binding_handle
*h
)
178 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
179 struct dcerpc_bh_state
);
189 if (hs
->p
->conn
->dead
) {
196 static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle
*h
,
199 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
200 struct dcerpc_bh_state
);
204 return DCERPC_REQUEST_TIMEOUT
;
207 old
= hs
->p
->request_timeout
;
208 hs
->p
->request_timeout
= timeout
;
213 static void dcerpc_bh_auth_info(struct dcerpc_binding_handle
*h
,
214 enum dcerpc_AuthType
*auth_type
,
215 enum dcerpc_AuthLevel
*auth_level
)
217 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
218 struct dcerpc_bh_state
);
224 if (hs
->p
->conn
== NULL
) {
228 *auth_type
= hs
->p
->conn
->security_state
.auth_type
;
229 *auth_level
= hs
->p
->conn
->security_state
.auth_level
;
232 struct dcerpc_bh_raw_call_state
{
233 struct tevent_context
*ev
;
234 struct dcerpc_binding_handle
*h
;
240 static void dcerpc_bh_raw_call_done(struct rpc_request
*subreq
);
242 static struct tevent_req
*dcerpc_bh_raw_call_send(TALLOC_CTX
*mem_ctx
,
243 struct tevent_context
*ev
,
244 struct dcerpc_binding_handle
*h
,
245 const struct GUID
*object
,
248 const uint8_t *in_data
,
251 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
252 struct dcerpc_bh_state
);
253 struct tevent_req
*req
;
254 struct dcerpc_bh_raw_call_state
*state
;
256 struct rpc_request
*subreq
;
258 req
= tevent_req_create(mem_ctx
, &state
,
259 struct dcerpc_bh_raw_call_state
);
265 state
->in_data
.data
= discard_const_p(uint8_t, in_data
);
266 state
->in_data
.length
= in_length
;
268 ok
= dcerpc_bh_is_connected(h
);
270 tevent_req_nterror(req
, NT_STATUS_CONNECTION_DISCONNECTED
);
271 return tevent_req_post(req
, ev
);
274 subreq
= dcerpc_request_send(state
,
279 if (tevent_req_nomem(subreq
, req
)) {
280 return tevent_req_post(req
, ev
);
282 subreq
->async
.callback
= dcerpc_bh_raw_call_done
;
283 subreq
->async
.private_data
= req
;
288 static void dcerpc_bh_raw_call_done(struct rpc_request
*subreq
)
290 struct tevent_req
*req
=
291 talloc_get_type_abort(subreq
->async
.private_data
,
293 struct dcerpc_bh_raw_call_state
*state
=
295 struct dcerpc_bh_raw_call_state
);
299 state
->out_flags
= 0;
300 if (subreq
->flags
& DCERPC_PULL_BIGENDIAN
) {
301 state
->out_flags
|= LIBNDR_FLAG_BIGENDIAN
;
304 fault_code
= subreq
->fault_code
;
306 status
= dcerpc_request_recv(subreq
, state
, &state
->out_data
);
307 if (NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
308 status
= dcerpc_fault_to_nt_status(fault_code
);
312 * We trigger the callback in the next event run
313 * because the code in this file might trigger
314 * multiple request callbacks from within a single
317 * In order to avoid segfaults from within
318 * dcerpc_connection_dead() we call
319 * tevent_req_defer_callback().
321 tevent_req_defer_callback(req
, state
->ev
);
323 if (!NT_STATUS_IS_OK(status
)) {
324 tevent_req_nterror(req
, status
);
328 tevent_req_done(req
);
331 static NTSTATUS
dcerpc_bh_raw_call_recv(struct tevent_req
*req
,
337 struct dcerpc_bh_raw_call_state
*state
=
339 struct dcerpc_bh_raw_call_state
);
342 if (tevent_req_is_nterror(req
, &status
)) {
343 tevent_req_received(req
);
347 *out_data
= talloc_move(mem_ctx
, &state
->out_data
.data
);
348 *out_length
= state
->out_data
.length
;
349 *out_flags
= state
->out_flags
;
350 tevent_req_received(req
);
354 struct dcerpc_bh_disconnect_state
{
358 static struct tevent_req
*dcerpc_bh_disconnect_send(TALLOC_CTX
*mem_ctx
,
359 struct tevent_context
*ev
,
360 struct dcerpc_binding_handle
*h
)
362 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
363 struct dcerpc_bh_state
);
364 struct tevent_req
*req
;
365 struct dcerpc_bh_disconnect_state
*state
;
368 req
= tevent_req_create(mem_ctx
, &state
,
369 struct dcerpc_bh_disconnect_state
);
374 ok
= dcerpc_bh_is_connected(h
);
376 tevent_req_nterror(req
, NT_STATUS_CONNECTION_DISCONNECTED
);
377 return tevent_req_post(req
, ev
);
380 /* TODO: do a real disconnect ... */
383 tevent_req_done(req
);
384 return tevent_req_post(req
, ev
);
387 static NTSTATUS
dcerpc_bh_disconnect_recv(struct tevent_req
*req
)
391 if (tevent_req_is_nterror(req
, &status
)) {
392 tevent_req_received(req
);
396 tevent_req_received(req
);
400 static bool dcerpc_bh_push_bigendian(struct dcerpc_binding_handle
*h
)
402 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
403 struct dcerpc_bh_state
);
405 if (hs
->p
->conn
->flags
& DCERPC_PUSH_BIGENDIAN
) {
412 static bool dcerpc_bh_ref_alloc(struct dcerpc_binding_handle
*h
)
414 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
415 struct dcerpc_bh_state
);
417 if (hs
->p
->conn
->flags
& DCERPC_NDR_REF_ALLOC
) {
424 static bool dcerpc_bh_use_ndr64(struct dcerpc_binding_handle
*h
)
426 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
427 struct dcerpc_bh_state
);
429 if (hs
->p
->conn
->flags
& DCERPC_NDR64
) {
436 static void dcerpc_bh_do_ndr_print(struct dcerpc_binding_handle
*h
,
438 const void *_struct_ptr
,
439 const struct ndr_interface_call
*call
)
441 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
442 struct dcerpc_bh_state
);
443 void *struct_ptr
= discard_const(_struct_ptr
);
445 if (ndr_flags
& NDR_IN
) {
446 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_PRINT_IN
) {
447 ndr_print_function_debug(call
->ndr_print
,
453 if (ndr_flags
& NDR_OUT
) {
454 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_PRINT_OUT
) {
455 ndr_print_function_debug(call
->ndr_print
,
463 static void dcerpc_bh_ndr_push_failed(struct dcerpc_binding_handle
*h
,
465 const void *struct_ptr
,
466 const struct ndr_interface_call
*call
)
468 DEBUG(2,("Unable to ndr_push structure for %s - %s\n",
469 call
->name
, nt_errstr(error
)));
472 static void dcerpc_bh_ndr_pull_failed(struct dcerpc_binding_handle
*h
,
474 const DATA_BLOB
*blob
,
475 const struct ndr_interface_call
*call
)
477 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
478 struct dcerpc_bh_state
);
479 const uint32_t num_examples
= 20;
482 DEBUG(2,("Unable to ndr_pull structure for %s - %s\n",
483 call
->name
, nt_errstr(error
)));
485 if (hs
->p
->conn
->packet_log_dir
== NULL
) return;
487 for (i
=0;i
<num_examples
;i
++) {
489 asprintf(&name
, "%s/rpclog/%s-out.%d",
490 hs
->p
->conn
->packet_log_dir
,
495 if (!file_exist(name
)) {
496 if (file_save(name
, blob
->data
, blob
->length
)) {
497 DEBUG(10,("Logged rpc packet to %s\n", name
));
506 static NTSTATUS
dcerpc_bh_ndr_validate_in(struct dcerpc_binding_handle
*h
,
508 const DATA_BLOB
*blob
,
509 const struct ndr_interface_call
*call
)
511 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
512 struct dcerpc_bh_state
);
514 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_VALIDATE_IN
) {
517 status
= dcerpc_ndr_validate_in(hs
->p
->conn
,
523 if (!NT_STATUS_IS_OK(status
)) {
524 DEBUG(0,("Validation [in] failed for %s - %s\n",
525 call
->name
, nt_errstr(status
)));
530 DEBUG(10,("rpc request data:\n"));
531 dump_data(10, blob
->data
, blob
->length
);
536 static NTSTATUS
dcerpc_bh_ndr_validate_out(struct dcerpc_binding_handle
*h
,
537 struct ndr_pull
*pull_in
,
538 const void *_struct_ptr
,
539 const struct ndr_interface_call
*call
)
541 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
542 struct dcerpc_bh_state
);
543 void *struct_ptr
= discard_const(_struct_ptr
);
545 DEBUG(10,("rpc reply data:\n"));
546 dump_data(10, pull_in
->data
, pull_in
->data_size
);
548 if (pull_in
->offset
!= pull_in
->data_size
) {
549 DEBUG(0,("Warning! ignoring %u unread bytes at ofs:%u (0x%08X) for %s!\n",
550 pull_in
->data_size
- pull_in
->offset
,
551 pull_in
->offset
, pull_in
->offset
,
553 /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here,
554 but it turns out that early versions of NT
555 (specifically NT3.1) add junk onto the end of rpc
556 packets, so if we want to interoperate at all with
557 those versions then we need to ignore this error */
560 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_VALIDATE_OUT
) {
563 status
= dcerpc_ndr_validate_out(hs
->p
->conn
,
570 if (!NT_STATUS_IS_OK(status
)) {
571 DEBUG(2,("Validation [out] failed for %s - %s\n",
572 call
->name
, nt_errstr(status
)));
580 static const struct dcerpc_binding_handle_ops dcerpc_bh_ops
= {
582 .is_connected
= dcerpc_bh_is_connected
,
583 .set_timeout
= dcerpc_bh_set_timeout
,
584 .auth_info
= dcerpc_bh_auth_info
,
585 .raw_call_send
= dcerpc_bh_raw_call_send
,
586 .raw_call_recv
= dcerpc_bh_raw_call_recv
,
587 .disconnect_send
= dcerpc_bh_disconnect_send
,
588 .disconnect_recv
= dcerpc_bh_disconnect_recv
,
590 .push_bigendian
= dcerpc_bh_push_bigendian
,
591 .ref_alloc
= dcerpc_bh_ref_alloc
,
592 .use_ndr64
= dcerpc_bh_use_ndr64
,
593 .do_ndr_print
= dcerpc_bh_do_ndr_print
,
594 .ndr_push_failed
= dcerpc_bh_ndr_push_failed
,
595 .ndr_pull_failed
= dcerpc_bh_ndr_pull_failed
,
596 .ndr_validate_in
= dcerpc_bh_ndr_validate_in
,
597 .ndr_validate_out
= dcerpc_bh_ndr_validate_out
,
600 /* initialise a dcerpc pipe. */
601 struct dcerpc_binding_handle
*dcerpc_pipe_binding_handle(struct dcerpc_pipe
*p
)
603 struct dcerpc_binding_handle
*h
;
604 struct dcerpc_bh_state
*hs
;
606 h
= dcerpc_binding_handle_create(p
,
611 struct dcerpc_bh_state
,
618 dcerpc_binding_handle_set_sync_ev(h
, p
->conn
->event_ctx
);
623 /* initialise a dcerpc pipe. */
624 _PUBLIC_
struct dcerpc_pipe
*dcerpc_pipe_init(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
)
626 struct dcerpc_pipe
*p
;
628 p
= talloc_zero(mem_ctx
, struct dcerpc_pipe
);
633 p
->conn
= dcerpc_connection_init(p
, ev
);
634 if (p
->conn
== NULL
) {
639 p
->last_fault_code
= 0;
641 p
->request_timeout
= DCERPC_REQUEST_TIMEOUT
;
644 ZERO_STRUCT(p
->syntax
);
645 ZERO_STRUCT(p
->transfer_syntax
);
648 p
->conn
->flags
|= DCERPC_DEBUG_PRINT_BOTH
;
651 p
->binding_handle
= dcerpc_pipe_binding_handle(p
);
652 if (p
->binding_handle
== NULL
) {
662 choose the next call id to use
664 static uint32_t next_call_id(struct dcecli_connection
*c
)
667 if (c
->call_id
== 0) {
674 setup for a ndr pull, also setting up any flags from the binding string
676 static struct ndr_pull
*ndr_pull_init_flags(struct dcecli_connection
*c
,
677 DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
)
679 struct ndr_pull
*ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
681 if (ndr
== NULL
) return ndr
;
683 if (c
->flags
& DCERPC_DEBUG_PAD_CHECK
) {
684 ndr
->flags
|= LIBNDR_FLAG_PAD_CHECK
;
687 if (c
->flags
& DCERPC_NDR_REF_ALLOC
) {
688 ndr
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
691 if (c
->flags
& DCERPC_NDR64
) {
692 ndr
->flags
|= LIBNDR_FLAG_NDR64
;
699 parse a data blob into a ncacn_packet structure. This handles both
700 input and output packets
702 static NTSTATUS
ncacn_pull(struct dcecli_connection
*c
, DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
703 struct ncacn_packet
*pkt
)
705 struct ndr_pull
*ndr
;
706 enum ndr_err_code ndr_err
;
708 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
710 return NT_STATUS_NO_MEMORY
;
713 if (! (CVAL(blob
->data
, DCERPC_DREP_OFFSET
) & DCERPC_DREP_LE
)) {
714 ndr
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
717 if (CVAL(blob
->data
, DCERPC_PFC_OFFSET
) & DCERPC_PFC_FLAG_OBJECT_UUID
) {
718 ndr
->flags
|= LIBNDR_FLAG_OBJECT_PRESENT
;
721 ndr_err
= ndr_pull_ncacn_packet(ndr
, NDR_SCALARS
|NDR_BUFFERS
, pkt
);
723 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
724 return ndr_map_error2ntstatus(ndr_err
);
727 if (pkt
->frag_length
!= blob
->length
) {
728 return NT_STATUS_RPC_PROTOCOL_ERROR
;
735 parse the authentication information on a dcerpc response packet
737 static NTSTATUS
ncacn_pull_request_auth(struct dcecli_connection
*c
, TALLOC_CTX
*mem_ctx
,
738 DATA_BLOB
*raw_packet
,
739 struct ncacn_packet
*pkt
)
742 struct dcerpc_auth auth
;
743 uint32_t auth_length
;
745 switch (c
->security_state
.auth_level
) {
746 case DCERPC_AUTH_LEVEL_PRIVACY
:
747 case DCERPC_AUTH_LEVEL_INTEGRITY
:
750 case DCERPC_AUTH_LEVEL_CONNECT
:
751 if (pkt
->auth_length
!= 0) {
755 case DCERPC_AUTH_LEVEL_NONE
:
756 if (pkt
->auth_length
!= 0) {
757 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
762 return NT_STATUS_INVALID_LEVEL
;
765 if (pkt
->auth_length
== 0) {
766 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
769 if (c
->security_state
.generic_state
== NULL
) {
770 return NT_STATUS_INTERNAL_ERROR
;
773 status
= dcerpc_pull_auth_trailer(pkt
, mem_ctx
,
774 &pkt
->u
.response
.stub_and_verifier
,
775 &auth
, &auth_length
, false);
776 NT_STATUS_NOT_OK_RETURN(status
);
778 pkt
->u
.response
.stub_and_verifier
.length
-= auth_length
;
780 /* check signature or unseal the packet */
781 switch (c
->security_state
.auth_level
) {
782 case DCERPC_AUTH_LEVEL_PRIVACY
:
783 status
= gensec_unseal_packet(c
->security_state
.generic_state
,
784 raw_packet
->data
+ DCERPC_REQUEST_LENGTH
,
785 pkt
->u
.response
.stub_and_verifier
.length
,
787 raw_packet
->length
- auth
.credentials
.length
,
789 memcpy(pkt
->u
.response
.stub_and_verifier
.data
,
790 raw_packet
->data
+ DCERPC_REQUEST_LENGTH
,
791 pkt
->u
.response
.stub_and_verifier
.length
);
794 case DCERPC_AUTH_LEVEL_INTEGRITY
:
795 status
= gensec_check_packet(c
->security_state
.generic_state
,
796 pkt
->u
.response
.stub_and_verifier
.data
,
797 pkt
->u
.response
.stub_and_verifier
.length
,
799 raw_packet
->length
- auth
.credentials
.length
,
803 case DCERPC_AUTH_LEVEL_CONNECT
:
804 /* for now we ignore possible signatures here */
805 status
= NT_STATUS_OK
;
809 status
= NT_STATUS_INVALID_LEVEL
;
813 /* remove the indicated amount of padding */
814 if (pkt
->u
.response
.stub_and_verifier
.length
< auth
.auth_pad_length
) {
815 return NT_STATUS_INFO_LENGTH_MISMATCH
;
817 pkt
->u
.response
.stub_and_verifier
.length
-= auth
.auth_pad_length
;
824 push a dcerpc request packet into a blob, possibly signing it.
826 static NTSTATUS
ncacn_push_request_sign(struct dcecli_connection
*c
,
827 DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
829 struct ncacn_packet
*pkt
)
832 struct ndr_push
*ndr
;
834 size_t payload_length
;
835 enum ndr_err_code ndr_err
;
836 size_t hdr_size
= DCERPC_REQUEST_LENGTH
;
837 struct dcerpc_auth auth_info
= {
838 .auth_type
= c
->security_state
.auth_type
,
839 .auth_level
= c
->security_state
.auth_level
,
840 .auth_context_id
= c
->security_state
.auth_context_id
,
843 switch (c
->security_state
.auth_level
) {
844 case DCERPC_AUTH_LEVEL_PRIVACY
:
845 case DCERPC_AUTH_LEVEL_INTEGRITY
:
847 return NT_STATUS_INTERNAL_ERROR
;
851 case DCERPC_AUTH_LEVEL_CONNECT
:
852 /* TODO: let the gensec mech decide if it wants to generate a signature */
853 return ncacn_push_auth(blob
, mem_ctx
, pkt
, NULL
);
855 case DCERPC_AUTH_LEVEL_NONE
:
856 return ncacn_push_auth(blob
, mem_ctx
, pkt
, NULL
);
859 return NT_STATUS_INVALID_LEVEL
;
862 ndr
= ndr_push_init_ctx(mem_ctx
);
864 return NT_STATUS_NO_MEMORY
;
867 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
868 ndr
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
871 if (c
->flags
& DCERPC_NDR64
) {
872 ndr
->flags
|= LIBNDR_FLAG_NDR64
;
875 if (pkt
->pfc_flags
& DCERPC_PFC_FLAG_OBJECT_UUID
) {
876 ndr
->flags
|= LIBNDR_FLAG_OBJECT_PRESENT
;
880 ndr_err
= ndr_push_ncacn_packet(ndr
, NDR_SCALARS
|NDR_BUFFERS
, pkt
);
881 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
882 return ndr_map_error2ntstatus(ndr_err
);
885 /* pad to 16 byte multiple in the payload portion of the
886 packet. This matches what w2k3 does. Note that we can't use
887 ndr_push_align() as that is relative to the start of the
888 whole packet, whereas w2k8 wants it relative to the start
890 auth_info
.auth_pad_length
=
891 DCERPC_AUTH_PAD_LENGTH(pkt
->u
.request
.stub_and_verifier
.length
);
892 ndr_err
= ndr_push_zero(ndr
, auth_info
.auth_pad_length
);
893 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
894 return ndr_map_error2ntstatus(ndr_err
);
897 payload_length
= pkt
->u
.request
.stub_and_verifier
.length
+
898 auth_info
.auth_pad_length
;
900 /* add the auth verifier */
901 ndr_err
= ndr_push_dcerpc_auth(ndr
, NDR_SCALARS
|NDR_BUFFERS
, &auth_info
);
902 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
903 return ndr_map_error2ntstatus(ndr_err
);
906 /* extract the whole packet as a blob */
907 *blob
= ndr_push_blob(ndr
);
910 * Setup the frag and auth length in the packet buffer.
911 * This is needed if the GENSEC mech does AEAD signing
912 * of the packet headers. The signature itself will be
915 dcerpc_set_frag_length(blob
, blob
->length
+ sig_size
);
916 dcerpc_set_auth_length(blob
, sig_size
);
918 /* sign or seal the packet */
919 switch (c
->security_state
.auth_level
) {
920 case DCERPC_AUTH_LEVEL_PRIVACY
:
921 status
= gensec_seal_packet(c
->security_state
.generic_state
,
923 blob
->data
+ hdr_size
,
928 if (!NT_STATUS_IS_OK(status
)) {
933 case DCERPC_AUTH_LEVEL_INTEGRITY
:
934 status
= gensec_sign_packet(c
->security_state
.generic_state
,
936 blob
->data
+ hdr_size
,
941 if (!NT_STATUS_IS_OK(status
)) {
947 status
= NT_STATUS_INVALID_LEVEL
;
951 if (creds2
.length
!= sig_size
) {
952 /* this means the sig_size estimate for the signature
953 was incorrect. We have to correct the packet
954 sizes. That means we could go over the max fragment
956 DEBUG(3,("ncacn_push_request_sign: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n",
957 (unsigned) creds2
.length
,
959 (unsigned) auth_info
.auth_pad_length
,
960 (unsigned) pkt
->u
.request
.stub_and_verifier
.length
));
961 dcerpc_set_frag_length(blob
, blob
->length
+ creds2
.length
);
962 dcerpc_set_auth_length(blob
, creds2
.length
);
965 if (!data_blob_append(mem_ctx
, blob
, creds2
.data
, creds2
.length
)) {
966 return NT_STATUS_NO_MEMORY
;
974 fill in the fixed values in a dcerpc header
976 static void init_ncacn_hdr(struct dcecli_connection
*c
, struct ncacn_packet
*pkt
)
979 pkt
->rpc_vers_minor
= 0;
980 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
983 pkt
->drep
[0] = DCERPC_DREP_LE
;
991 map a bind nak reason to a NTSTATUS
993 static NTSTATUS
dcerpc_map_nak_reason(enum dcerpc_bind_nak_reason reason
)
996 case DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED
:
997 return NT_STATUS_REVISION_MISMATCH
;
998 case DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE
:
999 return NT_STATUS_INVALID_PARAMETER
;
1003 return NT_STATUS_UNSUCCESSFUL
;
1006 static NTSTATUS
dcerpc_map_ack_reason(const struct dcerpc_ack_ctx
*ack
)
1009 return NT_STATUS_RPC_PROTOCOL_ERROR
;
1012 switch (ack
->result
) {
1013 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK
:
1015 * We have not asked for this...
1017 return NT_STATUS_RPC_PROTOCOL_ERROR
;
1022 switch (ack
->reason
.value
) {
1023 case DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED
:
1024 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX
;
1025 case DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED
:
1026 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX
;
1030 return NT_STATUS_UNSUCCESSFUL
;
1034 remove requests from the pending or queued queues
1036 static int dcerpc_req_dequeue(struct rpc_request
*req
)
1038 switch (req
->state
) {
1039 case RPC_REQUEST_QUEUED
:
1040 DLIST_REMOVE(req
->p
->conn
->request_queue
, req
);
1042 case RPC_REQUEST_PENDING
:
1043 DLIST_REMOVE(req
->p
->conn
->pending
, req
);
1045 case RPC_REQUEST_DONE
:
1053 mark the dcerpc connection dead. All outstanding requests get an error
1055 static void dcerpc_connection_dead(struct dcecli_connection
*conn
, NTSTATUS status
)
1057 if (conn
->dead
) return;
1061 TALLOC_FREE(conn
->io_trigger
);
1062 conn
->io_trigger_pending
= false;
1064 dcerpc_shutdown_pipe(conn
, status
);
1066 /* all pending requests get the error */
1067 while (conn
->pending
) {
1068 struct rpc_request
*req
= conn
->pending
;
1069 dcerpc_req_dequeue(req
);
1070 req
->state
= RPC_REQUEST_DONE
;
1071 req
->status
= status
;
1072 if (req
->async
.callback
) {
1073 req
->async
.callback(req
);
1077 /* all requests, which are not shipped */
1078 while (conn
->request_queue
) {
1079 struct rpc_request
*req
= conn
->request_queue
;
1080 dcerpc_req_dequeue(req
);
1081 req
->state
= RPC_REQUEST_DONE
;
1082 req
->status
= status
;
1083 if (req
->async
.callback
) {
1084 req
->async
.callback(req
);
1088 talloc_set_destructor(conn
, NULL
);
1089 if (conn
->free_skipped
) {
1095 forward declarations of the recv_data handlers for the types of
1096 packets we need to handle
1098 static void dcerpc_request_recv_data(struct dcecli_connection
*c
,
1099 DATA_BLOB
*raw_packet
, struct ncacn_packet
*pkt
);
1102 receive a dcerpc reply from the transport. Here we work out what
1103 type of reply it is (normal request, bind or alter context) and
1104 dispatch to the appropriate handler
1106 static void dcerpc_recv_data(struct dcecli_connection
*conn
, DATA_BLOB
*blob
, NTSTATUS status
)
1108 struct ncacn_packet pkt
;
1114 if (NT_STATUS_IS_OK(status
) && blob
->length
== 0) {
1115 status
= NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
1118 /* the transport may be telling us of a severe error, such as
1120 if (!NT_STATUS_IS_OK(status
)) {
1121 data_blob_free(blob
);
1122 dcerpc_connection_dead(conn
, status
);
1126 /* parse the basic packet to work out what type of response this is */
1127 status
= ncacn_pull(conn
, blob
, blob
->data
, &pkt
);
1128 if (!NT_STATUS_IS_OK(status
)) {
1129 data_blob_free(blob
);
1130 dcerpc_connection_dead(conn
, status
);
1134 dcerpc_request_recv_data(conn
, blob
, &pkt
);
1138 handle timeouts of individual dcerpc requests
1140 static void dcerpc_timeout_handler(struct tevent_context
*ev
, struct tevent_timer
*te
,
1141 struct timeval t
, void *private_data
)
1143 struct rpc_request
*req
= talloc_get_type(private_data
, struct rpc_request
);
1145 if (req
->ignore_timeout
) {
1146 dcerpc_req_dequeue(req
);
1147 req
->state
= RPC_REQUEST_DONE
;
1148 req
->status
= NT_STATUS_IO_TIMEOUT
;
1149 if (req
->async
.callback
) {
1150 req
->async
.callback(req
);
1155 dcerpc_connection_dead(req
->p
->conn
, NT_STATUS_IO_TIMEOUT
);
1158 struct dcerpc_bind_state
{
1159 struct tevent_context
*ev
;
1160 struct dcerpc_pipe
*p
;
1163 static void dcerpc_bind_fail_handler(struct rpc_request
*subreq
);
1164 static void dcerpc_bind_recv_handler(struct rpc_request
*subreq
,
1165 DATA_BLOB
*raw_packet
,
1166 struct ncacn_packet
*pkt
);
1168 struct tevent_req
*dcerpc_bind_send(TALLOC_CTX
*mem_ctx
,
1169 struct tevent_context
*ev
,
1170 struct dcerpc_pipe
*p
,
1171 const struct ndr_syntax_id
*syntax
,
1172 const struct ndr_syntax_id
*transfer_syntax
)
1174 struct tevent_req
*req
;
1175 struct dcerpc_bind_state
*state
;
1176 struct ncacn_packet pkt
;
1179 struct rpc_request
*subreq
;
1182 req
= tevent_req_create(mem_ctx
, &state
,
1183 struct dcerpc_bind_state
);
1191 p
->syntax
= *syntax
;
1192 p
->transfer_syntax
= *transfer_syntax
;
1194 flags
= dcerpc_binding_get_flags(p
->binding
);
1196 init_ncacn_hdr(p
->conn
, &pkt
);
1198 pkt
.ptype
= DCERPC_PKT_BIND
;
1199 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
1200 pkt
.call_id
= p
->conn
->call_id
;
1201 pkt
.auth_length
= 0;
1203 if (flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
1204 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
1207 if (p
->conn
->flags
& DCERPC_PROPOSE_HEADER_SIGNING
) {
1208 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
;
1211 pkt
.u
.bind
.max_xmit_frag
= p
->conn
->srv_max_xmit_frag
;
1212 pkt
.u
.bind
.max_recv_frag
= p
->conn
->srv_max_recv_frag
;
1213 pkt
.u
.bind
.assoc_group_id
= dcerpc_binding_get_assoc_group_id(p
->binding
);
1214 pkt
.u
.bind
.num_contexts
= 1;
1215 pkt
.u
.bind
.ctx_list
= talloc_array(mem_ctx
, struct dcerpc_ctx_list
, 1);
1216 if (tevent_req_nomem(pkt
.u
.bind
.ctx_list
, req
)) {
1217 return tevent_req_post(req
, ev
);
1219 pkt
.u
.bind
.ctx_list
[0].context_id
= p
->context_id
;
1220 pkt
.u
.bind
.ctx_list
[0].num_transfer_syntaxes
= 1;
1221 pkt
.u
.bind
.ctx_list
[0].abstract_syntax
= p
->syntax
;
1222 pkt
.u
.bind
.ctx_list
[0].transfer_syntaxes
= &p
->transfer_syntax
;
1223 pkt
.u
.bind
.auth_info
= data_blob(NULL
, 0);
1225 /* construct the NDR form of the packet */
1226 status
= ncacn_push_auth(&blob
, state
, &pkt
,
1227 p
->conn
->security_state
.auth_info
);
1228 if (tevent_req_nterror(req
, status
)) {
1229 return tevent_req_post(req
, ev
);
1233 * we allocate a dcerpc_request so we can be in the same
1234 * request queue as normal requests
1236 subreq
= talloc_zero(state
, struct rpc_request
);
1237 if (tevent_req_nomem(subreq
, req
)) {
1238 return tevent_req_post(req
, ev
);
1241 subreq
->state
= RPC_REQUEST_PENDING
;
1242 subreq
->call_id
= pkt
.call_id
;
1243 subreq
->async
.private_data
= req
;
1244 subreq
->async
.callback
= dcerpc_bind_fail_handler
;
1246 subreq
->recv_handler
= dcerpc_bind_recv_handler
;
1247 DLIST_ADD_END(p
->conn
->pending
, subreq
, struct rpc_request
*);
1248 talloc_set_destructor(subreq
, dcerpc_req_dequeue
);
1250 status
= dcerpc_send_request(p
->conn
, &blob
, true);
1251 if (tevent_req_nterror(req
, status
)) {
1252 return tevent_req_post(req
, ev
);
1255 tevent_add_timer(ev
, subreq
,
1256 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT
, 0),
1257 dcerpc_timeout_handler
, subreq
);
1262 static void dcerpc_bind_fail_handler(struct rpc_request
*subreq
)
1264 struct tevent_req
*req
=
1265 talloc_get_type_abort(subreq
->async
.private_data
,
1267 struct dcerpc_bind_state
*state
=
1268 tevent_req_data(req
,
1269 struct dcerpc_bind_state
);
1270 NTSTATUS status
= subreq
->status
;
1272 TALLOC_FREE(subreq
);
1275 * We trigger the callback in the next event run
1276 * because the code in this file might trigger
1277 * multiple request callbacks from within a single
1280 * In order to avoid segfaults from within
1281 * dcerpc_connection_dead() we call
1282 * tevent_req_defer_callback().
1284 tevent_req_defer_callback(req
, state
->ev
);
1286 tevent_req_nterror(req
, status
);
1289 static void dcerpc_bind_recv_handler(struct rpc_request
*subreq
,
1290 DATA_BLOB
*raw_packet
,
1291 struct ncacn_packet
*pkt
)
1293 struct tevent_req
*req
=
1294 talloc_get_type_abort(subreq
->async
.private_data
,
1296 struct dcerpc_bind_state
*state
=
1297 tevent_req_data(req
,
1298 struct dcerpc_bind_state
);
1299 struct dcecli_connection
*conn
= state
->p
->conn
;
1300 struct dcerpc_binding
*b
= NULL
;
1305 * Note that pkt is allocated under raw_packet->data,
1306 * while raw_packet->data is a child of subreq.
1308 talloc_steal(state
, raw_packet
->data
);
1309 TALLOC_FREE(subreq
);
1312 * We trigger the callback in the next event run
1313 * because the code in this file might trigger
1314 * multiple request callbacks from within a single
1317 * In order to avoid segfaults from within
1318 * dcerpc_connection_dead() we call
1319 * tevent_req_defer_callback().
1321 tevent_req_defer_callback(req
, state
->ev
);
1323 if (pkt
->ptype
== DCERPC_PKT_BIND_NAK
) {
1324 status
= dcerpc_map_nak_reason(pkt
->u
.bind_nak
.reject_reason
);
1326 DEBUG(2,("dcerpc: bind_nak reason %d - %s\n",
1327 pkt
->u
.bind_nak
.reject_reason
, nt_errstr(status
)));
1329 tevent_req_nterror(req
, status
);
1333 if ((pkt
->ptype
!= DCERPC_PKT_BIND_ACK
) ||
1334 (pkt
->u
.bind_ack
.num_results
== 0) ||
1335 (pkt
->u
.bind_ack
.ctx_list
[0].result
!= 0)) {
1336 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
1337 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
1342 * DCE-RPC 1.1 (c706) specifies
1343 * CONST_MUST_RCV_FRAG_SIZE as 1432
1345 if (pkt
->u
.bind_ack
.max_xmit_frag
< 1432) {
1346 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
1347 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
1350 if (pkt
->u
.bind_ack
.max_recv_frag
< 1432) {
1351 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
1352 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
1355 conn
->srv_max_xmit_frag
= MIN(conn
->srv_max_xmit_frag
,
1356 pkt
->u
.bind_ack
.max_xmit_frag
);
1357 conn
->srv_max_recv_frag
= MIN(conn
->srv_max_recv_frag
,
1358 pkt
->u
.bind_ack
.max_recv_frag
);
1360 flags
= dcerpc_binding_get_flags(state
->p
->binding
);
1362 if ((flags
& DCERPC_CONCURRENT_MULTIPLEX
) &&
1363 (pkt
->pfc_flags
& DCERPC_PFC_FLAG_CONC_MPX
)) {
1364 conn
->flags
|= DCERPC_CONCURRENT_MULTIPLEX
;
1367 if ((conn
->flags
& DCERPC_PROPOSE_HEADER_SIGNING
) &&
1368 (pkt
->pfc_flags
& DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
)) {
1369 conn
->flags
|= DCERPC_HEADER_SIGNING
;
1372 /* the bind_ack might contain a reply set of credentials */
1373 if (conn
->security_state
.auth_info
&& pkt
->u
.bind_ack
.auth_info
.length
) {
1374 uint32_t auth_length
;
1376 status
= dcerpc_pull_auth_trailer(pkt
, conn
, &pkt
->u
.bind_ack
.auth_info
,
1377 conn
->security_state
.auth_info
, &auth_length
, true);
1378 if (tevent_req_nterror(req
, status
)) {
1384 * We're the owner of the binding, so we're allowed to modify it.
1386 b
= discard_const_p(struct dcerpc_binding
, state
->p
->binding
);
1387 status
= dcerpc_binding_set_assoc_group_id(b
,
1388 pkt
->u
.bind_ack
.assoc_group_id
);
1389 if (tevent_req_nterror(req
, status
)) {
1393 tevent_req_done(req
);
1396 NTSTATUS
dcerpc_bind_recv(struct tevent_req
*req
)
1398 return tevent_req_simple_recv_ntstatus(req
);
1402 perform a continued bind (and auth3)
1404 NTSTATUS
dcerpc_auth3(struct dcerpc_pipe
*p
,
1405 TALLOC_CTX
*mem_ctx
)
1407 struct ncacn_packet pkt
;
1412 flags
= dcerpc_binding_get_flags(p
->binding
);
1414 init_ncacn_hdr(p
->conn
, &pkt
);
1416 pkt
.ptype
= DCERPC_PKT_AUTH3
;
1417 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
1418 pkt
.call_id
= next_call_id(p
->conn
);
1419 pkt
.auth_length
= 0;
1420 pkt
.u
.auth3
.auth_info
= data_blob(NULL
, 0);
1422 if (flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
1423 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
1426 /* construct the NDR form of the packet */
1427 status
= ncacn_push_auth(&blob
, mem_ctx
,
1429 p
->conn
->security_state
.auth_info
);
1430 if (!NT_STATUS_IS_OK(status
)) {
1434 /* send it on its way */
1435 status
= dcerpc_send_request(p
->conn
, &blob
, false);
1436 if (!NT_STATUS_IS_OK(status
)) {
1440 return NT_STATUS_OK
;
1445 process a fragment received from the transport layer during a
1448 This function frees the data
1450 static void dcerpc_request_recv_data(struct dcecli_connection
*c
,
1451 DATA_BLOB
*raw_packet
, struct ncacn_packet
*pkt
)
1453 struct rpc_request
*req
;
1454 unsigned int length
;
1455 NTSTATUS status
= NT_STATUS_OK
;
1458 if this is an authenticated connection then parse and check
1459 the auth info. We have to do this before finding the
1460 matching packet, as the request structure might have been
1461 removed due to a timeout, but if it has been we still need
1462 to run the auth routines so that we don't get the sign/seal
1463 info out of step with the server
1465 if (c
->security_state
.auth_info
&& c
->security_state
.generic_state
&&
1466 pkt
->ptype
== DCERPC_PKT_RESPONSE
) {
1467 status
= ncacn_pull_request_auth(c
, raw_packet
->data
, raw_packet
, pkt
);
1470 /* find the matching request */
1471 for (req
=c
->pending
;req
;req
=req
->next
) {
1472 if (pkt
->call_id
== req
->call_id
) break;
1476 /* useful for testing certain vendors RPC servers */
1477 if (req
== NULL
&& c
->pending
&& pkt
->call_id
== 0) {
1478 DEBUG(0,("HACK FOR INCORRECT CALL ID\n"));
1484 DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt
->call_id
));
1485 data_blob_free(raw_packet
);
1489 talloc_steal(req
, raw_packet
->data
);
1491 if (req
->recv_handler
!= NULL
) {
1492 dcerpc_req_dequeue(req
);
1493 req
->state
= RPC_REQUEST_DONE
;
1496 * We have to look at shipping further requests before calling
1497 * the async function, that one might close the pipe
1499 dcerpc_schedule_io_trigger(c
);
1501 req
->recv_handler(req
, raw_packet
, pkt
);
1505 if (pkt
->ptype
== DCERPC_PKT_FAULT
) {
1506 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c
, pkt
->u
.fault
.status
)));
1507 req
->fault_code
= pkt
->u
.fault
.status
;
1508 req
->status
= NT_STATUS_NET_WRITE_FAULT
;
1512 if (pkt
->ptype
!= DCERPC_PKT_RESPONSE
) {
1513 DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
1515 req
->fault_code
= DCERPC_FAULT_OTHER
;
1516 req
->status
= NT_STATUS_NET_WRITE_FAULT
;
1520 /* now check the status from the auth routines, and if it failed then fail
1521 this request accordingly */
1522 if (!NT_STATUS_IS_OK(status
)) {
1523 req
->status
= status
;
1527 length
= pkt
->u
.response
.stub_and_verifier
.length
;
1530 req
->payload
.data
= talloc_realloc(req
,
1533 req
->payload
.length
+ length
);
1534 if (!req
->payload
.data
) {
1535 req
->status
= NT_STATUS_NO_MEMORY
;
1538 memcpy(req
->payload
.data
+req
->payload
.length
,
1539 pkt
->u
.response
.stub_and_verifier
.data
, length
);
1540 req
->payload
.length
+= length
;
1543 if (!(pkt
->pfc_flags
& DCERPC_PFC_FLAG_LAST
)) {
1544 data_blob_free(raw_packet
);
1545 dcerpc_send_read(c
);
1549 if (req
->verify_bitmask1
) {
1550 req
->p
->conn
->security_state
.verified_bitmask1
= true;
1552 if (req
->verify_pcontext
) {
1553 req
->p
->verified_pcontext
= true;
1556 if (!(pkt
->drep
[0] & DCERPC_DREP_LE
)) {
1557 req
->flags
|= DCERPC_PULL_BIGENDIAN
;
1559 req
->flags
&= ~DCERPC_PULL_BIGENDIAN
;
1563 data_blob_free(raw_packet
);
1565 /* we've got the full payload */
1566 dcerpc_req_dequeue(req
);
1567 req
->state
= RPC_REQUEST_DONE
;
1570 * We have to look at shipping further requests before calling
1571 * the async function, that one might close the pipe
1573 dcerpc_schedule_io_trigger(c
);
1575 if (req
->async
.callback
) {
1576 req
->async
.callback(req
);
1580 static NTSTATUS
dcerpc_request_prepare_vt(struct rpc_request
*req
);
1583 perform the send side of a async dcerpc request
1585 static struct rpc_request
*dcerpc_request_send(TALLOC_CTX
*mem_ctx
,
1586 struct dcerpc_pipe
*p
,
1587 const struct GUID
*object
,
1589 DATA_BLOB
*stub_data
)
1591 struct rpc_request
*req
;
1594 req
= talloc_zero(mem_ctx
, struct rpc_request
);
1600 req
->call_id
= next_call_id(p
->conn
);
1601 req
->state
= RPC_REQUEST_QUEUED
;
1603 if (object
!= NULL
) {
1604 req
->object
= (struct GUID
*)talloc_memdup(req
, (const void *)object
, sizeof(*object
));
1605 if (req
->object
== NULL
) {
1612 req
->request_data
.length
= stub_data
->length
;
1613 req
->request_data
.data
= stub_data
->data
;
1615 status
= dcerpc_request_prepare_vt(req
);
1616 if (!NT_STATUS_IS_OK(status
)) {
1621 DLIST_ADD_END(p
->conn
->request_queue
, req
, struct rpc_request
*);
1622 talloc_set_destructor(req
, dcerpc_req_dequeue
);
1624 dcerpc_schedule_io_trigger(p
->conn
);
1626 if (p
->request_timeout
) {
1627 tevent_add_timer(p
->conn
->event_ctx
, req
,
1628 timeval_current_ofs(p
->request_timeout
, 0),
1629 dcerpc_timeout_handler
, req
);
1635 static NTSTATUS
dcerpc_request_prepare_vt(struct rpc_request
*req
)
1637 struct dcecli_security
*sec
= &req
->p
->conn
->security_state
;
1638 struct dcerpc_sec_verification_trailer
*t
;
1639 struct dcerpc_sec_vt
*c
= NULL
;
1640 struct ndr_push
*ndr
= NULL
;
1641 enum ndr_err_code ndr_err
;
1643 if (sec
->auth_info
== NULL
) {
1644 return NT_STATUS_OK
;
1647 if (sec
->auth_info
->auth_level
< DCERPC_AUTH_LEVEL_INTEGRITY
) {
1648 return NT_STATUS_OK
;
1651 t
= talloc_zero(req
, struct dcerpc_sec_verification_trailer
);
1653 return NT_STATUS_NO_MEMORY
;
1656 if (!sec
->verified_bitmask1
) {
1657 t
->commands
= talloc_realloc(t
, t
->commands
,
1658 struct dcerpc_sec_vt
,
1659 t
->count
.count
+ 1);
1660 if (t
->commands
== NULL
) {
1661 return NT_STATUS_NO_MEMORY
;
1663 c
= &t
->commands
[t
->count
.count
++];
1666 c
->command
= DCERPC_SEC_VT_COMMAND_BITMASK1
;
1667 if (req
->p
->conn
->flags
& DCERPC_PROPOSE_HEADER_SIGNING
) {
1668 c
->u
.bitmask1
= DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING
;
1670 req
->verify_bitmask1
= true;
1673 if (!req
->p
->verified_pcontext
) {
1674 t
->commands
= talloc_realloc(t
, t
->commands
,
1675 struct dcerpc_sec_vt
,
1676 t
->count
.count
+ 1);
1677 if (t
->commands
== NULL
) {
1678 return NT_STATUS_NO_MEMORY
;
1680 c
= &t
->commands
[t
->count
.count
++];
1683 c
->command
= DCERPC_SEC_VT_COMMAND_PCONTEXT
;
1684 c
->u
.pcontext
.abstract_syntax
= req
->p
->syntax
;
1685 c
->u
.pcontext
.transfer_syntax
= req
->p
->transfer_syntax
;
1687 req
->verify_pcontext
= true;
1690 if (!(req
->p
->conn
->flags
& DCERPC_HEADER_SIGNING
)) {
1691 t
->commands
= talloc_realloc(t
, t
->commands
,
1692 struct dcerpc_sec_vt
,
1693 t
->count
.count
+ 1);
1694 if (t
->commands
== NULL
) {
1695 return NT_STATUS_NO_MEMORY
;
1697 c
= &t
->commands
[t
->count
.count
++];
1700 c
->command
= DCERPC_SEC_VT_COMMAND_HEADER2
;
1701 c
->u
.header2
.ptype
= DCERPC_PKT_REQUEST
;
1702 if (req
->p
->conn
->flags
& DCERPC_PUSH_BIGENDIAN
) {
1703 c
->u
.header2
.drep
[0] = 0;
1705 c
->u
.header2
.drep
[0] = DCERPC_DREP_LE
;
1707 c
->u
.header2
.drep
[1] = 0;
1708 c
->u
.header2
.drep
[2] = 0;
1709 c
->u
.header2
.drep
[3] = 0;
1710 c
->u
.header2
.call_id
= req
->call_id
;
1711 c
->u
.header2
.context_id
= req
->p
->context_id
;
1712 c
->u
.header2
.opnum
= req
->opnum
;
1715 if (t
->count
.count
== 0) {
1717 return NT_STATUS_OK
;
1720 c
= &t
->commands
[t
->count
.count
- 1];
1721 c
->command
|= DCERPC_SEC_VT_COMMAND_END
;
1723 if (DEBUGLEVEL
>= 10) {
1724 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer
, t
);
1727 ndr
= ndr_push_init_ctx(req
);
1729 return NT_STATUS_NO_MEMORY
;
1733 * for now we just copy and append
1736 ndr_err
= ndr_push_bytes(ndr
, req
->request_data
.data
,
1737 req
->request_data
.length
);
1738 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1739 return ndr_map_error2ntstatus(ndr_err
);
1742 ndr_err
= ndr_push_dcerpc_sec_verification_trailer(ndr
,
1743 NDR_SCALARS
| NDR_BUFFERS
,
1745 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1746 return ndr_map_error2ntstatus(ndr_err
);
1748 req
->request_data
= ndr_push_blob(ndr
);
1750 return NT_STATUS_OK
;
1754 Send a request using the transport
1757 static void dcerpc_ship_next_request(struct dcecli_connection
*c
)
1759 struct rpc_request
*req
;
1760 struct dcerpc_pipe
*p
;
1761 DATA_BLOB
*stub_data
;
1762 struct ncacn_packet pkt
;
1764 uint32_t remaining
, chunk_size
;
1765 bool first_packet
= true;
1766 size_t sig_size
= 0;
1767 bool need_async
= false;
1768 bool can_async
= true;
1770 req
= c
->request_queue
;
1776 stub_data
= &req
->request_data
;
1782 if (c
->security_state
.auth_info
&&
1783 c
->security_state
.generic_state
)
1785 struct gensec_security
*gensec
= c
->security_state
.generic_state
;
1787 switch (c
->security_state
.auth_info
->auth_level
) {
1788 case DCERPC_AUTH_LEVEL_PRIVACY
:
1789 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1790 can_async
= gensec_have_feature(gensec
,
1791 GENSEC_FEATURE_ASYNC_REPLIES
);
1793 case DCERPC_AUTH_LEVEL_CONNECT
:
1794 case DCERPC_AUTH_LEVEL_NONE
:
1803 if (need_async
&& !can_async
) {
1804 req
->wait_for_sync
= true;
1808 DLIST_REMOVE(c
->request_queue
, req
);
1809 DLIST_ADD(c
->pending
, req
);
1810 req
->state
= RPC_REQUEST_PENDING
;
1812 init_ncacn_hdr(p
->conn
, &pkt
);
1814 remaining
= stub_data
->length
;
1816 /* we can write a full max_recv_frag size, minus the dcerpc
1817 request header size */
1818 chunk_size
= p
->conn
->srv_max_recv_frag
;
1819 chunk_size
-= DCERPC_REQUEST_LENGTH
;
1820 if (c
->security_state
.auth_info
&&
1821 c
->security_state
.generic_state
) {
1822 size_t max_payload
= chunk_size
;
1824 max_payload
-= DCERPC_AUTH_TRAILER_LENGTH
;
1825 max_payload
-= (max_payload
% DCERPC_AUTH_PAD_ALIGNMENT
);
1827 sig_size
= gensec_sig_size(c
->security_state
.generic_state
,
1830 chunk_size
-= DCERPC_AUTH_TRAILER_LENGTH
;
1831 chunk_size
-= sig_size
;
1834 chunk_size
-= (chunk_size
% DCERPC_AUTH_PAD_ALIGNMENT
);
1836 pkt
.ptype
= DCERPC_PKT_REQUEST
;
1837 pkt
.call_id
= req
->call_id
;
1838 pkt
.auth_length
= 0;
1840 pkt
.u
.request
.context_id
= p
->context_id
;
1841 pkt
.u
.request
.opnum
= req
->opnum
;
1844 pkt
.u
.request
.object
.object
= *req
->object
;
1845 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_OBJECT_UUID
;
1846 chunk_size
-= ndr_size_GUID(req
->object
,0);
1849 /* we send a series of pdus without waiting for a reply */
1850 while (remaining
> 0 || first_packet
) {
1851 uint32_t chunk
= MIN(chunk_size
, remaining
);
1852 bool last_frag
= false;
1853 bool do_trans
= false;
1855 first_packet
= false;
1856 pkt
.pfc_flags
&= ~(DCERPC_PFC_FLAG_FIRST
|DCERPC_PFC_FLAG_LAST
);
1858 if (remaining
== stub_data
->length
) {
1859 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_FIRST
;
1861 if (chunk
== remaining
) {
1862 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_LAST
;
1866 pkt
.u
.request
.alloc_hint
= remaining
;
1867 pkt
.u
.request
.stub_and_verifier
.data
= stub_data
->data
+
1868 (stub_data
->length
- remaining
);
1869 pkt
.u
.request
.stub_and_verifier
.length
= chunk
;
1871 req
->status
= ncacn_push_request_sign(p
->conn
, &blob
, req
, sig_size
, &pkt
);
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
&& !need_async
) {
1882 req
->status
= dcerpc_send_request(p
->conn
, &blob
, do_trans
);
1883 if (!NT_STATUS_IS_OK(req
->status
)) {
1884 req
->state
= RPC_REQUEST_DONE
;
1885 DLIST_REMOVE(p
->conn
->pending
, req
);
1889 if (last_frag
&& !do_trans
) {
1890 req
->status
= dcerpc_send_read(p
->conn
);
1891 if (!NT_STATUS_IS_OK(req
->status
)) {
1892 req
->state
= RPC_REQUEST_DONE
;
1893 DLIST_REMOVE(p
->conn
->pending
, req
);
1902 static void dcerpc_io_trigger(struct tevent_context
*ctx
,
1903 struct tevent_immediate
*im
,
1906 struct dcecli_connection
*c
=
1907 talloc_get_type_abort(private_data
,
1908 struct dcecli_connection
);
1910 c
->io_trigger_pending
= false;
1912 dcerpc_schedule_io_trigger(c
);
1914 dcerpc_ship_next_request(c
);
1917 static void dcerpc_schedule_io_trigger(struct dcecli_connection
*c
)
1923 if (c
->request_queue
== NULL
) {
1927 if (c
->request_queue
->wait_for_sync
&& c
->pending
) {
1931 if (c
->io_trigger_pending
) {
1935 c
->io_trigger_pending
= true;
1937 tevent_schedule_immediate(c
->io_trigger
,
1944 perform the receive side of a async dcerpc request
1946 static NTSTATUS
dcerpc_request_recv(struct rpc_request
*req
,
1947 TALLOC_CTX
*mem_ctx
,
1948 DATA_BLOB
*stub_data
)
1952 while (req
->state
!= RPC_REQUEST_DONE
) {
1953 struct tevent_context
*ctx
= req
->p
->conn
->event_ctx
;
1954 if (tevent_loop_once(ctx
) != 0) {
1955 return NT_STATUS_CONNECTION_DISCONNECTED
;
1958 *stub_data
= req
->payload
;
1959 status
= req
->status
;
1960 if (stub_data
->data
) {
1961 stub_data
->data
= talloc_steal(mem_ctx
, stub_data
->data
);
1963 if (NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
1964 req
->p
->last_fault_code
= req
->fault_code
;
1966 talloc_unlink(talloc_parent(req
), req
);
1971 this is a paranoid NDR validator. For every packet we push onto the wire
1972 we pull it back again, then push it again. Then we compare the raw NDR data
1973 for that to the NDR we initially generated. If they don't match then we know
1974 we must have a bug in either the pull or push side of our code
1976 static NTSTATUS
dcerpc_ndr_validate_in(struct dcecli_connection
*c
,
1977 TALLOC_CTX
*mem_ctx
,
1980 ndr_push_flags_fn_t ndr_push
,
1981 ndr_pull_flags_fn_t ndr_pull
)
1984 struct ndr_pull
*pull
;
1985 struct ndr_push
*push
;
1987 enum ndr_err_code ndr_err
;
1989 st
= talloc_size(mem_ctx
, struct_size
);
1991 return NT_STATUS_NO_MEMORY
;
1994 pull
= ndr_pull_init_flags(c
, &blob
, mem_ctx
);
1996 return NT_STATUS_NO_MEMORY
;
1998 pull
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
2000 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
2001 pull
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
2004 if (c
->flags
& DCERPC_NDR64
) {
2005 pull
->flags
|= LIBNDR_FLAG_NDR64
;
2008 ndr_err
= ndr_pull(pull
, NDR_IN
, st
);
2009 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2010 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
2011 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
2012 "failed input validation pull - %s",
2014 return ndr_map_error2ntstatus(ndr_err
);
2017 push
= ndr_push_init_ctx(mem_ctx
);
2019 return NT_STATUS_NO_MEMORY
;
2022 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
2023 push
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
2026 if (c
->flags
& DCERPC_NDR64
) {
2027 push
->flags
|= LIBNDR_FLAG_NDR64
;
2030 ndr_err
= ndr_push(push
, NDR_IN
, st
);
2031 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2032 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
2033 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
2034 "failed input validation push - %s",
2036 return ndr_map_error2ntstatus(ndr_err
);
2039 blob2
= ndr_push_blob(push
);
2041 if (data_blob_cmp(&blob
, &blob2
) != 0) {
2042 DEBUG(3,("original:\n"));
2043 dump_data(3, blob
.data
, blob
.length
);
2044 DEBUG(3,("secondary:\n"));
2045 dump_data(3, blob2
.data
, blob2
.length
);
2046 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
2047 "failed input validation blobs doesn't match");
2048 return ndr_map_error2ntstatus(ndr_err
);
2051 return NT_STATUS_OK
;
2055 this is a paranoid NDR input validator. For every packet we pull
2056 from the wire we push it back again then pull and push it
2057 again. Then we compare the raw NDR data for that to the NDR we
2058 initially generated. If they don't match then we know we must have a
2059 bug in either the pull or push side of our code
2061 static NTSTATUS
dcerpc_ndr_validate_out(struct dcecli_connection
*c
,
2062 struct ndr_pull
*pull_in
,
2065 ndr_push_flags_fn_t ndr_push
,
2066 ndr_pull_flags_fn_t ndr_pull
,
2067 ndr_print_function_t ndr_print
)
2070 struct ndr_pull
*pull
;
2071 struct ndr_push
*push
;
2072 DATA_BLOB blob
, blob2
;
2073 TALLOC_CTX
*mem_ctx
= pull_in
;
2075 enum ndr_err_code ndr_err
;
2077 st
= talloc_size(mem_ctx
, struct_size
);
2079 return NT_STATUS_NO_MEMORY
;
2081 memcpy(st
, struct_ptr
, struct_size
);
2083 push
= ndr_push_init_ctx(mem_ctx
);
2085 return NT_STATUS_NO_MEMORY
;
2088 ndr_err
= ndr_push(push
, NDR_OUT
, struct_ptr
);
2089 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2090 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
2091 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
2092 "failed output validation push - %s",
2094 return ndr_map_error2ntstatus(ndr_err
);
2097 blob
= ndr_push_blob(push
);
2099 pull
= ndr_pull_init_flags(c
, &blob
, mem_ctx
);
2101 return NT_STATUS_NO_MEMORY
;
2104 pull
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
2105 ndr_err
= ndr_pull(pull
, NDR_OUT
, st
);
2106 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2107 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
2108 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
2109 "failed output validation pull - %s",
2111 return ndr_map_error2ntstatus(ndr_err
);
2114 push
= ndr_push_init_ctx(mem_ctx
);
2116 return NT_STATUS_NO_MEMORY
;
2119 ndr_err
= ndr_push(push
, NDR_OUT
, st
);
2120 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2121 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
2122 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
2123 "failed output validation push2 - %s",
2125 return ndr_map_error2ntstatus(ndr_err
);
2128 blob2
= ndr_push_blob(push
);
2130 if (data_blob_cmp(&blob
, &blob2
) != 0) {
2131 DEBUG(3,("original:\n"));
2132 dump_data(3, blob
.data
, blob
.length
);
2133 DEBUG(3,("secondary:\n"));
2134 dump_data(3, blob2
.data
, blob2
.length
);
2135 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
2136 "failed output validation blobs doesn't match");
2137 return ndr_map_error2ntstatus(ndr_err
);
2140 /* this checks the printed forms of the two structures, which effectively
2141 tests all of the value() attributes */
2142 s1
= ndr_print_function_string(mem_ctx
, ndr_print
, "VALIDATE",
2143 NDR_OUT
, struct_ptr
);
2144 s2
= ndr_print_function_string(mem_ctx
, ndr_print
, "VALIDATE",
2146 if (strcmp(s1
, s2
) != 0) {
2148 DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1
, s2
));
2150 /* this is sometimes useful */
2151 printf("VALIDATE ERROR\n");
2152 file_save("wire.dat", s1
, strlen(s1
));
2153 file_save("gen.dat", s2
, strlen(s2
));
2154 system("diff -u wire.dat gen.dat");
2156 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
2157 "failed output validation strings doesn't match");
2158 return ndr_map_error2ntstatus(ndr_err
);
2161 return NT_STATUS_OK
;
2165 a useful function for retrieving the server name we connected to
2167 _PUBLIC_
const char *dcerpc_server_name(struct dcerpc_pipe
*p
)
2169 return p
->conn
? p
->conn
->server_name
: NULL
;
2174 get the dcerpc auth_level for a open connection
2176 uint32_t dcerpc_auth_level(struct dcecli_connection
*c
)
2180 if (c
->flags
& DCERPC_SEAL
) {
2181 auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
2182 } else if (c
->flags
& DCERPC_SIGN
) {
2183 auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
2184 } else if (c
->flags
& DCERPC_CONNECT
) {
2185 auth_level
= DCERPC_AUTH_LEVEL_CONNECT
;
2187 auth_level
= DCERPC_AUTH_LEVEL_NONE
;
2192 struct dcerpc_alter_context_state
{
2193 struct tevent_context
*ev
;
2194 struct dcerpc_pipe
*p
;
2197 static void dcerpc_alter_context_fail_handler(struct rpc_request
*subreq
);
2198 static void dcerpc_alter_context_recv_handler(struct rpc_request
*req
,
2199 DATA_BLOB
*raw_packet
,
2200 struct ncacn_packet
*pkt
);
2202 struct tevent_req
*dcerpc_alter_context_send(TALLOC_CTX
*mem_ctx
,
2203 struct tevent_context
*ev
,
2204 struct dcerpc_pipe
*p
,
2205 const struct ndr_syntax_id
*syntax
,
2206 const struct ndr_syntax_id
*transfer_syntax
)
2208 struct tevent_req
*req
;
2209 struct dcerpc_alter_context_state
*state
;
2210 struct ncacn_packet pkt
;
2213 struct rpc_request
*subreq
;
2216 req
= tevent_req_create(mem_ctx
, &state
,
2217 struct dcerpc_alter_context_state
);
2225 p
->syntax
= *syntax
;
2226 p
->transfer_syntax
= *transfer_syntax
;
2228 flags
= dcerpc_binding_get_flags(p
->binding
);
2230 init_ncacn_hdr(p
->conn
, &pkt
);
2232 pkt
.ptype
= DCERPC_PKT_ALTER
;
2233 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
2234 pkt
.call_id
= p
->conn
->call_id
;
2235 pkt
.auth_length
= 0;
2237 if (flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
2238 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
2241 pkt
.u
.alter
.max_xmit_frag
= p
->conn
->srv_max_xmit_frag
;
2242 pkt
.u
.alter
.max_recv_frag
= p
->conn
->srv_max_recv_frag
;
2243 pkt
.u
.alter
.assoc_group_id
= dcerpc_binding_get_assoc_group_id(p
->binding
);
2244 pkt
.u
.alter
.num_contexts
= 1;
2245 pkt
.u
.alter
.ctx_list
= talloc_array(state
, struct dcerpc_ctx_list
, 1);
2246 if (tevent_req_nomem(pkt
.u
.alter
.ctx_list
, req
)) {
2247 return tevent_req_post(req
, ev
);
2249 pkt
.u
.alter
.ctx_list
[0].context_id
= p
->context_id
;
2250 pkt
.u
.alter
.ctx_list
[0].num_transfer_syntaxes
= 1;
2251 pkt
.u
.alter
.ctx_list
[0].abstract_syntax
= p
->syntax
;
2252 pkt
.u
.alter
.ctx_list
[0].transfer_syntaxes
= &p
->transfer_syntax
;
2253 pkt
.u
.alter
.auth_info
= data_blob(NULL
, 0);
2255 /* construct the NDR form of the packet */
2256 status
= ncacn_push_auth(&blob
, state
, &pkt
,
2257 p
->conn
->security_state
.auth_info
);
2258 if (tevent_req_nterror(req
, status
)) {
2259 return tevent_req_post(req
, ev
);
2263 * we allocate a dcerpc_request so we can be in the same
2264 * request queue as normal requests
2266 subreq
= talloc_zero(state
, struct rpc_request
);
2267 if (tevent_req_nomem(subreq
, req
)) {
2268 return tevent_req_post(req
, ev
);
2271 subreq
->state
= RPC_REQUEST_PENDING
;
2272 subreq
->call_id
= pkt
.call_id
;
2273 subreq
->async
.private_data
= req
;
2274 subreq
->async
.callback
= dcerpc_alter_context_fail_handler
;
2276 subreq
->recv_handler
= dcerpc_alter_context_recv_handler
;
2277 DLIST_ADD_END(p
->conn
->pending
, subreq
, struct rpc_request
*);
2278 talloc_set_destructor(subreq
, dcerpc_req_dequeue
);
2280 status
= dcerpc_send_request(p
->conn
, &blob
, true);
2281 if (tevent_req_nterror(req
, status
)) {
2282 return tevent_req_post(req
, ev
);
2285 tevent_add_timer(ev
, subreq
,
2286 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT
, 0),
2287 dcerpc_timeout_handler
, subreq
);
2292 static void dcerpc_alter_context_fail_handler(struct rpc_request
*subreq
)
2294 struct tevent_req
*req
=
2295 talloc_get_type_abort(subreq
->async
.private_data
,
2297 struct dcerpc_alter_context_state
*state
=
2298 tevent_req_data(req
,
2299 struct dcerpc_alter_context_state
);
2300 NTSTATUS status
= subreq
->status
;
2302 TALLOC_FREE(subreq
);
2305 * We trigger the callback in the next event run
2306 * because the code in this file might trigger
2307 * multiple request callbacks from within a single
2310 * In order to avoid segfaults from within
2311 * dcerpc_connection_dead() we call
2312 * tevent_req_defer_callback().
2314 tevent_req_defer_callback(req
, state
->ev
);
2316 tevent_req_nterror(req
, status
);
2319 static void dcerpc_alter_context_recv_handler(struct rpc_request
*subreq
,
2320 DATA_BLOB
*raw_packet
,
2321 struct ncacn_packet
*pkt
)
2323 struct tevent_req
*req
=
2324 talloc_get_type_abort(subreq
->async
.private_data
,
2326 struct dcerpc_alter_context_state
*state
=
2327 tevent_req_data(req
,
2328 struct dcerpc_alter_context_state
);
2329 struct dcecli_connection
*conn
= state
->p
->conn
;
2333 * Note that pkt is allocated under raw_packet->data,
2334 * while raw_packet->data is a child of subreq.
2336 talloc_steal(state
, raw_packet
->data
);
2337 TALLOC_FREE(subreq
);
2340 * We trigger the callback in the next event run
2341 * because the code in this file might trigger
2342 * multiple request callbacks from within a single
2345 * In order to avoid segfaults from within
2346 * dcerpc_connection_dead() we call
2347 * tevent_req_defer_callback().
2349 tevent_req_defer_callback(req
, state
->ev
);
2351 if (pkt
->ptype
== DCERPC_PKT_ALTER_RESP
&&
2352 pkt
->u
.alter_resp
.num_results
== 1 &&
2353 pkt
->u
.alter_resp
.ctx_list
[0].result
!= 0) {
2354 status
= dcerpc_map_ack_reason(&pkt
->u
.alter_resp
.ctx_list
[0]);
2355 DEBUG(2,("dcerpc: alter_resp failed - reason %d - %s\n",
2356 pkt
->u
.alter_resp
.ctx_list
[0].reason
.value
,
2357 nt_errstr(status
)));
2358 tevent_req_nterror(req
, status
);
2362 if (pkt
->ptype
== DCERPC_PKT_FAULT
) {
2363 DEBUG(5,("dcerpc: alter_resp - rpc fault: %s\n",
2364 dcerpc_errstr(state
, pkt
->u
.fault
.status
)));
2365 if (pkt
->u
.fault
.status
== DCERPC_FAULT_ACCESS_DENIED
) {
2366 state
->p
->last_fault_code
= pkt
->u
.fault
.status
;
2367 tevent_req_nterror(req
, NT_STATUS_LOGON_FAILURE
);
2368 } else if (pkt
->u
.fault
.status
== DCERPC_FAULT_SEC_PKG_ERROR
) {
2369 state
->p
->last_fault_code
= pkt
->u
.fault
.status
;
2370 tevent_req_nterror(req
, NT_STATUS_LOGON_FAILURE
);
2372 state
->p
->last_fault_code
= pkt
->u
.fault
.status
;
2373 status
= dcerpc_fault_to_nt_status(pkt
->u
.fault
.status
);
2374 tevent_req_nterror(req
, status
);
2379 if (pkt
->ptype
!= DCERPC_PKT_ALTER_RESP
||
2380 pkt
->u
.alter_resp
.num_results
== 0 ||
2381 pkt
->u
.alter_resp
.ctx_list
[0].result
!= 0) {
2382 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
2383 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
2387 /* the alter_resp might contain a reply set of credentials */
2388 if (conn
->security_state
.auth_info
&&
2389 pkt
->u
.alter_resp
.auth_info
.length
) {
2390 uint32_t auth_length
;
2392 status
= dcerpc_pull_auth_trailer(pkt
, conn
, &pkt
->u
.alter_resp
.auth_info
,
2393 conn
->security_state
.auth_info
, &auth_length
, true);
2394 if (tevent_req_nterror(req
, status
)) {
2399 tevent_req_done(req
);
2402 NTSTATUS
dcerpc_alter_context_recv(struct tevent_req
*req
)
2404 return tevent_req_simple_recv_ntstatus(req
);
2408 send a dcerpc alter_context request
2410 _PUBLIC_ NTSTATUS
dcerpc_alter_context(struct dcerpc_pipe
*p
,
2411 TALLOC_CTX
*mem_ctx
,
2412 const struct ndr_syntax_id
*syntax
,
2413 const struct ndr_syntax_id
*transfer_syntax
)
2415 struct tevent_req
*subreq
;
2416 struct tevent_context
*ev
= p
->conn
->event_ctx
;
2419 /* TODO: create a new event context here */
2421 subreq
= dcerpc_alter_context_send(mem_ctx
, ev
,
2422 p
, syntax
, transfer_syntax
);
2423 if (subreq
== NULL
) {
2424 return NT_STATUS_NO_MEMORY
;
2427 ok
= tevent_req_poll(subreq
, ev
);
2430 status
= map_nt_error_from_unix_common(errno
);
2434 return dcerpc_alter_context_recv(subreq
);
2437 static void dcerpc_transport_dead(struct dcecli_connection
*c
, NTSTATUS status
)
2439 if (c
->transport
.stream
== NULL
) {
2443 tevent_queue_stop(c
->transport
.write_queue
);
2444 TALLOC_FREE(c
->transport
.read_subreq
);
2445 TALLOC_FREE(c
->transport
.stream
);
2447 if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL
, status
)) {
2448 status
= NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
2451 if (NT_STATUS_EQUAL(NT_STATUS_OK
, status
)) {
2452 status
= NT_STATUS_END_OF_FILE
;
2455 dcerpc_recv_data(c
, NULL
, status
);
2460 shutdown SMB pipe connection
2462 struct dcerpc_shutdown_pipe_state
{
2463 struct dcecli_connection
*c
;
2467 static void dcerpc_shutdown_pipe_done(struct tevent_req
*subreq
);
2469 static NTSTATUS
dcerpc_shutdown_pipe(struct dcecli_connection
*c
, NTSTATUS status
)
2471 struct dcerpc_shutdown_pipe_state
*state
;
2472 struct tevent_req
*subreq
;
2474 if (c
->transport
.stream
== NULL
) {
2475 return NT_STATUS_OK
;
2478 state
= talloc_zero(c
, struct dcerpc_shutdown_pipe_state
);
2479 if (state
== NULL
) {
2480 return NT_STATUS_NO_MEMORY
;
2483 state
->status
= status
;
2485 subreq
= tstream_disconnect_send(state
, c
->event_ctx
, c
->transport
.stream
);
2486 if (subreq
== NULL
) {
2487 return NT_STATUS_NO_MEMORY
;
2489 tevent_req_set_callback(subreq
, dcerpc_shutdown_pipe_done
, state
);
2494 static void dcerpc_shutdown_pipe_done(struct tevent_req
*subreq
)
2496 struct dcerpc_shutdown_pipe_state
*state
=
2497 tevent_req_callback_data(subreq
, struct dcerpc_shutdown_pipe_state
);
2498 struct dcecli_connection
*c
= state
->c
;
2499 NTSTATUS status
= state
->status
;
2503 * here we ignore the return values...
2505 tstream_disconnect_recv(subreq
, &error
);
2506 TALLOC_FREE(subreq
);
2510 dcerpc_transport_dead(c
, status
);
2515 struct dcerpc_send_read_state
{
2516 struct dcecli_connection
*p
;
2519 static int dcerpc_send_read_state_destructor(struct dcerpc_send_read_state
*state
)
2521 struct dcecli_connection
*p
= state
->p
;
2523 p
->transport
.read_subreq
= NULL
;
2528 static void dcerpc_send_read_done(struct tevent_req
*subreq
);
2530 static NTSTATUS
dcerpc_send_read(struct dcecli_connection
*p
)
2532 struct dcerpc_send_read_state
*state
;
2534 if (p
->transport
.read_subreq
!= NULL
) {
2535 p
->transport
.pending_reads
++;
2536 return NT_STATUS_OK
;
2539 state
= talloc_zero(p
, struct dcerpc_send_read_state
);
2540 if (state
== NULL
) {
2541 return NT_STATUS_NO_MEMORY
;
2545 talloc_set_destructor(state
, dcerpc_send_read_state_destructor
);
2547 p
->transport
.read_subreq
= dcerpc_read_ncacn_packet_send(state
,
2549 p
->transport
.stream
);
2550 if (p
->transport
.read_subreq
== NULL
) {
2551 return NT_STATUS_NO_MEMORY
;
2553 tevent_req_set_callback(p
->transport
.read_subreq
, dcerpc_send_read_done
, state
);
2555 return NT_STATUS_OK
;
2558 static void dcerpc_send_read_done(struct tevent_req
*subreq
)
2560 struct dcerpc_send_read_state
*state
=
2561 tevent_req_callback_data(subreq
,
2562 struct dcerpc_send_read_state
);
2563 struct dcecli_connection
*p
= state
->p
;
2565 struct ncacn_packet
*pkt
;
2568 status
= dcerpc_read_ncacn_packet_recv(subreq
, state
,
2570 TALLOC_FREE(subreq
);
2571 if (!NT_STATUS_IS_OK(status
)) {
2573 dcerpc_transport_dead(p
, status
);
2578 * here we steal into thet connection context,
2579 * but p->transport.recv_data() will steal or free it again
2581 talloc_steal(p
, blob
.data
);
2584 if (p
->transport
.pending_reads
> 0) {
2585 p
->transport
.pending_reads
--;
2587 status
= dcerpc_send_read(p
);
2588 if (!NT_STATUS_IS_OK(status
)) {
2589 dcerpc_transport_dead(p
, status
);
2594 dcerpc_recv_data(p
, &blob
, NT_STATUS_OK
);
2597 struct dcerpc_send_request_state
{
2598 struct dcecli_connection
*p
;
2603 static int dcerpc_send_request_state_destructor(struct dcerpc_send_request_state
*state
)
2605 struct dcecli_connection
*p
= state
->p
;
2607 p
->transport
.read_subreq
= NULL
;
2612 static void dcerpc_send_request_wait_done(struct tevent_req
*subreq
);
2613 static void dcerpc_send_request_done(struct tevent_req
*subreq
);
2615 static NTSTATUS
dcerpc_send_request(struct dcecli_connection
*p
, DATA_BLOB
*data
,
2618 struct dcerpc_send_request_state
*state
;
2619 struct tevent_req
*subreq
;
2620 bool use_trans
= trigger_read
;
2622 if (p
->transport
.stream
== NULL
) {
2623 return NT_STATUS_CONNECTION_DISCONNECTED
;
2626 state
= talloc_zero(p
, struct dcerpc_send_request_state
);
2627 if (state
== NULL
) {
2628 return NT_STATUS_NO_MEMORY
;
2632 state
->blob
= data_blob_talloc(state
, data
->data
, data
->length
);
2633 if (state
->blob
.data
== NULL
) {
2635 return NT_STATUS_NO_MEMORY
;
2637 state
->iov
.iov_base
= (void *)state
->blob
.data
;
2638 state
->iov
.iov_len
= state
->blob
.length
;
2640 if (p
->transport
.read_subreq
!= NULL
) {
2644 if (!tstream_is_smbXcli_np(p
->transport
.stream
)) {
2650 * we need to block reads until our write is
2651 * the next in the write queue.
2653 p
->transport
.read_subreq
= tevent_queue_wait_send(state
, p
->event_ctx
,
2654 p
->transport
.write_queue
);
2655 if (p
->transport
.read_subreq
== NULL
) {
2657 return NT_STATUS_NO_MEMORY
;
2659 tevent_req_set_callback(p
->transport
.read_subreq
,
2660 dcerpc_send_request_wait_done
,
2663 talloc_set_destructor(state
, dcerpc_send_request_state_destructor
);
2665 trigger_read
= false;
2668 subreq
= tstream_writev_queue_send(state
, p
->event_ctx
,
2669 p
->transport
.stream
,
2670 p
->transport
.write_queue
,
2672 if (subreq
== NULL
) {
2674 return NT_STATUS_NO_MEMORY
;
2676 tevent_req_set_callback(subreq
, dcerpc_send_request_done
, state
);
2679 dcerpc_send_read(p
);
2682 return NT_STATUS_OK
;
2685 static void dcerpc_send_request_wait_done(struct tevent_req
*subreq
)
2687 struct dcerpc_send_request_state
*state
=
2688 tevent_req_callback_data(subreq
,
2689 struct dcerpc_send_request_state
);
2690 struct dcecli_connection
*p
= state
->p
;
2694 p
->transport
.read_subreq
= NULL
;
2695 talloc_set_destructor(state
, NULL
);
2697 ok
= tevent_queue_wait_recv(subreq
);
2700 dcerpc_transport_dead(p
, NT_STATUS_NO_MEMORY
);
2704 if (tevent_queue_length(p
->transport
.write_queue
) <= 2) {
2705 status
= tstream_smbXcli_np_use_trans(p
->transport
.stream
);
2706 if (!NT_STATUS_IS_OK(status
)) {
2708 dcerpc_transport_dead(p
, status
);
2713 /* we free subreq after tstream_cli_np_use_trans */
2714 TALLOC_FREE(subreq
);
2716 dcerpc_send_read(p
);
2719 static void dcerpc_send_request_done(struct tevent_req
*subreq
)
2721 struct dcerpc_send_request_state
*state
=
2722 tevent_req_callback_data(subreq
,
2723 struct dcerpc_send_request_state
);
2727 ret
= tstream_writev_queue_recv(subreq
, &error
);
2728 TALLOC_FREE(subreq
);
2730 struct dcecli_connection
*p
= state
->p
;
2731 NTSTATUS status
= map_nt_error_from_unix_common(error
);
2734 dcerpc_transport_dead(p
, status
);