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
;
70 void (*callback
)(struct rpc_request
*);
75 _PUBLIC_ NTSTATUS
dcerpc_init(void)
80 static void dcerpc_connection_dead(struct dcecli_connection
*conn
, NTSTATUS status
);
81 static void dcerpc_schedule_io_trigger(struct dcecli_connection
*c
);
83 static struct rpc_request
*dcerpc_request_send(TALLOC_CTX
*mem_ctx
,
84 struct dcerpc_pipe
*p
,
85 const struct GUID
*object
,
87 DATA_BLOB
*stub_data
);
88 static NTSTATUS
dcerpc_request_recv(struct rpc_request
*req
,
90 DATA_BLOB
*stub_data
);
91 static NTSTATUS
dcerpc_ndr_validate_in(struct dcecli_connection
*c
,
95 ndr_push_flags_fn_t ndr_push
,
96 ndr_pull_flags_fn_t ndr_pull
);
97 static NTSTATUS
dcerpc_ndr_validate_out(struct dcecli_connection
*c
,
98 struct ndr_pull
*pull_in
,
101 ndr_push_flags_fn_t ndr_push
,
102 ndr_pull_flags_fn_t ndr_pull
,
103 ndr_print_function_t ndr_print
);
104 static NTSTATUS
dcerpc_shutdown_pipe(struct dcecli_connection
*p
, NTSTATUS status
);
105 static NTSTATUS
dcerpc_send_request(struct dcecli_connection
*p
, DATA_BLOB
*data
,
107 static NTSTATUS
dcerpc_send_read(struct dcecli_connection
*p
);
109 /* destroy a dcerpc connection */
110 static int dcerpc_connection_destructor(struct dcecli_connection
*conn
)
113 conn
->free_skipped
= true;
116 dcerpc_connection_dead(conn
, NT_STATUS_LOCAL_DISCONNECT
);
121 /* initialise a dcerpc connection.
122 the event context is optional
124 static struct dcecli_connection
*dcerpc_connection_init(TALLOC_CTX
*mem_ctx
,
125 struct tevent_context
*ev
)
127 struct dcecli_connection
*c
;
129 c
= talloc_zero(mem_ctx
, struct dcecli_connection
);
136 if (c
->event_ctx
== NULL
) {
142 c
->security_state
.auth_info
= NULL
;
143 c
->security_state
.session_key
= dcerpc_generic_session_key
;
144 c
->security_state
.generic_state
= NULL
;
147 * Windows uses 5840 for ncacn_ip_tcp,
148 * so we also use it (for every transport)
149 * by default. But we give the transport
150 * the chance to overwrite it.
152 c
->srv_max_xmit_frag
= 5840;
153 c
->srv_max_recv_frag
= 5840;
156 c
->io_trigger
= tevent_create_immediate(c
);
157 if (c
->io_trigger
== NULL
) {
162 talloc_set_destructor(c
, dcerpc_connection_destructor
);
167 struct dcerpc_bh_state
{
168 struct dcerpc_pipe
*p
;
171 static bool dcerpc_bh_is_connected(struct dcerpc_binding_handle
*h
)
173 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
174 struct dcerpc_bh_state
);
184 if (hs
->p
->conn
->dead
) {
191 static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle
*h
,
194 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
195 struct dcerpc_bh_state
);
199 return DCERPC_REQUEST_TIMEOUT
;
202 old
= hs
->p
->request_timeout
;
203 hs
->p
->request_timeout
= timeout
;
208 static void dcerpc_bh_auth_info(struct dcerpc_binding_handle
*h
,
209 enum dcerpc_AuthType
*auth_type
,
210 enum dcerpc_AuthLevel
*auth_level
)
212 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
213 struct dcerpc_bh_state
);
219 if (hs
->p
->conn
== NULL
) {
223 if (hs
->p
->conn
->security_state
.auth_info
== NULL
) {
227 *auth_type
= hs
->p
->conn
->security_state
.auth_info
->auth_type
;
228 *auth_level
= hs
->p
->conn
->security_state
.auth_info
->auth_level
;
231 struct dcerpc_bh_raw_call_state
{
232 struct tevent_context
*ev
;
233 struct dcerpc_binding_handle
*h
;
239 static void dcerpc_bh_raw_call_done(struct rpc_request
*subreq
);
241 static struct tevent_req
*dcerpc_bh_raw_call_send(TALLOC_CTX
*mem_ctx
,
242 struct tevent_context
*ev
,
243 struct dcerpc_binding_handle
*h
,
244 const struct GUID
*object
,
247 const uint8_t *in_data
,
250 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
251 struct dcerpc_bh_state
);
252 struct tevent_req
*req
;
253 struct dcerpc_bh_raw_call_state
*state
;
255 struct rpc_request
*subreq
;
257 req
= tevent_req_create(mem_ctx
, &state
,
258 struct dcerpc_bh_raw_call_state
);
264 state
->in_data
.data
= discard_const_p(uint8_t, in_data
);
265 state
->in_data
.length
= in_length
;
267 ok
= dcerpc_bh_is_connected(h
);
269 tevent_req_nterror(req
, NT_STATUS_CONNECTION_DISCONNECTED
);
270 return tevent_req_post(req
, ev
);
273 subreq
= dcerpc_request_send(state
,
278 if (tevent_req_nomem(subreq
, req
)) {
279 return tevent_req_post(req
, ev
);
281 subreq
->async
.callback
= dcerpc_bh_raw_call_done
;
282 subreq
->async
.private_data
= req
;
287 static void dcerpc_bh_raw_call_done(struct rpc_request
*subreq
)
289 struct tevent_req
*req
=
290 talloc_get_type_abort(subreq
->async
.private_data
,
292 struct dcerpc_bh_raw_call_state
*state
=
294 struct dcerpc_bh_raw_call_state
);
298 state
->out_flags
= 0;
299 if (subreq
->flags
& DCERPC_PULL_BIGENDIAN
) {
300 state
->out_flags
|= LIBNDR_FLAG_BIGENDIAN
;
303 fault_code
= subreq
->fault_code
;
305 status
= dcerpc_request_recv(subreq
, state
, &state
->out_data
);
306 if (NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
307 status
= dcerpc_fault_to_nt_status(fault_code
);
311 * We trigger the callback in the next event run
312 * because the code in this file might trigger
313 * multiple request callbacks from within a single
316 * In order to avoid segfaults from within
317 * dcerpc_connection_dead() we call
318 * tevent_req_defer_callback().
320 tevent_req_defer_callback(req
, state
->ev
);
322 if (!NT_STATUS_IS_OK(status
)) {
323 tevent_req_nterror(req
, status
);
327 tevent_req_done(req
);
330 static NTSTATUS
dcerpc_bh_raw_call_recv(struct tevent_req
*req
,
336 struct dcerpc_bh_raw_call_state
*state
=
338 struct dcerpc_bh_raw_call_state
);
341 if (tevent_req_is_nterror(req
, &status
)) {
342 tevent_req_received(req
);
346 *out_data
= talloc_move(mem_ctx
, &state
->out_data
.data
);
347 *out_length
= state
->out_data
.length
;
348 *out_flags
= state
->out_flags
;
349 tevent_req_received(req
);
353 struct dcerpc_bh_disconnect_state
{
357 static struct tevent_req
*dcerpc_bh_disconnect_send(TALLOC_CTX
*mem_ctx
,
358 struct tevent_context
*ev
,
359 struct dcerpc_binding_handle
*h
)
361 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
362 struct dcerpc_bh_state
);
363 struct tevent_req
*req
;
364 struct dcerpc_bh_disconnect_state
*state
;
367 req
= tevent_req_create(mem_ctx
, &state
,
368 struct dcerpc_bh_disconnect_state
);
373 ok
= dcerpc_bh_is_connected(h
);
375 tevent_req_nterror(req
, NT_STATUS_CONNECTION_DISCONNECTED
);
376 return tevent_req_post(req
, ev
);
379 /* TODO: do a real disconnect ... */
382 tevent_req_done(req
);
383 return tevent_req_post(req
, ev
);
386 static NTSTATUS
dcerpc_bh_disconnect_recv(struct tevent_req
*req
)
390 if (tevent_req_is_nterror(req
, &status
)) {
391 tevent_req_received(req
);
395 tevent_req_received(req
);
399 static bool dcerpc_bh_push_bigendian(struct dcerpc_binding_handle
*h
)
401 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
402 struct dcerpc_bh_state
);
404 if (hs
->p
->conn
->flags
& DCERPC_PUSH_BIGENDIAN
) {
411 static bool dcerpc_bh_ref_alloc(struct dcerpc_binding_handle
*h
)
413 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
414 struct dcerpc_bh_state
);
416 if (hs
->p
->conn
->flags
& DCERPC_NDR_REF_ALLOC
) {
423 static bool dcerpc_bh_use_ndr64(struct dcerpc_binding_handle
*h
)
425 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
426 struct dcerpc_bh_state
);
428 if (hs
->p
->conn
->flags
& DCERPC_NDR64
) {
435 static void dcerpc_bh_do_ndr_print(struct dcerpc_binding_handle
*h
,
437 const void *_struct_ptr
,
438 const struct ndr_interface_call
*call
)
440 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
441 struct dcerpc_bh_state
);
442 void *struct_ptr
= discard_const(_struct_ptr
);
444 if (ndr_flags
& NDR_IN
) {
445 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_PRINT_IN
) {
446 ndr_print_function_debug(call
->ndr_print
,
452 if (ndr_flags
& NDR_OUT
) {
453 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_PRINT_OUT
) {
454 ndr_print_function_debug(call
->ndr_print
,
462 static void dcerpc_bh_ndr_push_failed(struct dcerpc_binding_handle
*h
,
464 const void *struct_ptr
,
465 const struct ndr_interface_call
*call
)
467 DEBUG(2,("Unable to ndr_push structure for %s - %s\n",
468 call
->name
, nt_errstr(error
)));
471 static void dcerpc_bh_ndr_pull_failed(struct dcerpc_binding_handle
*h
,
473 const DATA_BLOB
*blob
,
474 const struct ndr_interface_call
*call
)
476 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
477 struct dcerpc_bh_state
);
478 const uint32_t num_examples
= 20;
481 DEBUG(2,("Unable to ndr_pull structure for %s - %s\n",
482 call
->name
, nt_errstr(error
)));
484 if (hs
->p
->conn
->packet_log_dir
== NULL
) return;
486 for (i
=0;i
<num_examples
;i
++) {
488 asprintf(&name
, "%s/rpclog/%s-out.%d",
489 hs
->p
->conn
->packet_log_dir
,
494 if (!file_exist(name
)) {
495 if (file_save(name
, blob
->data
, blob
->length
)) {
496 DEBUG(10,("Logged rpc packet to %s\n", name
));
505 static NTSTATUS
dcerpc_bh_ndr_validate_in(struct dcerpc_binding_handle
*h
,
507 const DATA_BLOB
*blob
,
508 const struct ndr_interface_call
*call
)
510 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
511 struct dcerpc_bh_state
);
513 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_VALIDATE_IN
) {
516 status
= dcerpc_ndr_validate_in(hs
->p
->conn
,
522 if (!NT_STATUS_IS_OK(status
)) {
523 DEBUG(0,("Validation [in] failed for %s - %s\n",
524 call
->name
, nt_errstr(status
)));
529 DEBUG(10,("rpc request data:\n"));
530 dump_data(10, blob
->data
, blob
->length
);
535 static NTSTATUS
dcerpc_bh_ndr_validate_out(struct dcerpc_binding_handle
*h
,
536 struct ndr_pull
*pull_in
,
537 const void *_struct_ptr
,
538 const struct ndr_interface_call
*call
)
540 struct dcerpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
541 struct dcerpc_bh_state
);
542 void *struct_ptr
= discard_const(_struct_ptr
);
544 DEBUG(10,("rpc reply data:\n"));
545 dump_data(10, pull_in
->data
, pull_in
->data_size
);
547 if (pull_in
->offset
!= pull_in
->data_size
) {
548 DEBUG(0,("Warning! ignoring %u unread bytes at ofs:%u (0x%08X) for %s!\n",
549 pull_in
->data_size
- pull_in
->offset
,
550 pull_in
->offset
, pull_in
->offset
,
552 /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here,
553 but it turns out that early versions of NT
554 (specifically NT3.1) add junk onto the end of rpc
555 packets, so if we want to interoperate at all with
556 those versions then we need to ignore this error */
559 if (hs
->p
->conn
->flags
& DCERPC_DEBUG_VALIDATE_OUT
) {
562 status
= dcerpc_ndr_validate_out(hs
->p
->conn
,
569 if (!NT_STATUS_IS_OK(status
)) {
570 DEBUG(2,("Validation [out] failed for %s - %s\n",
571 call
->name
, nt_errstr(status
)));
579 static const struct dcerpc_binding_handle_ops dcerpc_bh_ops
= {
581 .is_connected
= dcerpc_bh_is_connected
,
582 .set_timeout
= dcerpc_bh_set_timeout
,
583 .auth_info
= dcerpc_bh_auth_info
,
584 .raw_call_send
= dcerpc_bh_raw_call_send
,
585 .raw_call_recv
= dcerpc_bh_raw_call_recv
,
586 .disconnect_send
= dcerpc_bh_disconnect_send
,
587 .disconnect_recv
= dcerpc_bh_disconnect_recv
,
589 .push_bigendian
= dcerpc_bh_push_bigendian
,
590 .ref_alloc
= dcerpc_bh_ref_alloc
,
591 .use_ndr64
= dcerpc_bh_use_ndr64
,
592 .do_ndr_print
= dcerpc_bh_do_ndr_print
,
593 .ndr_push_failed
= dcerpc_bh_ndr_push_failed
,
594 .ndr_pull_failed
= dcerpc_bh_ndr_pull_failed
,
595 .ndr_validate_in
= dcerpc_bh_ndr_validate_in
,
596 .ndr_validate_out
= dcerpc_bh_ndr_validate_out
,
599 /* initialise a dcerpc pipe. */
600 struct dcerpc_binding_handle
*dcerpc_pipe_binding_handle(struct dcerpc_pipe
*p
)
602 struct dcerpc_binding_handle
*h
;
603 struct dcerpc_bh_state
*hs
;
605 h
= dcerpc_binding_handle_create(p
,
610 struct dcerpc_bh_state
,
617 dcerpc_binding_handle_set_sync_ev(h
, p
->conn
->event_ctx
);
622 /* initialise a dcerpc pipe. */
623 _PUBLIC_
struct dcerpc_pipe
*dcerpc_pipe_init(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
)
625 struct dcerpc_pipe
*p
;
627 p
= talloc_zero(mem_ctx
, struct dcerpc_pipe
);
632 p
->conn
= dcerpc_connection_init(p
, ev
);
633 if (p
->conn
== NULL
) {
638 p
->last_fault_code
= 0;
640 p
->request_timeout
= DCERPC_REQUEST_TIMEOUT
;
643 ZERO_STRUCT(p
->syntax
);
644 ZERO_STRUCT(p
->transfer_syntax
);
647 p
->conn
->flags
|= DCERPC_DEBUG_PRINT_BOTH
;
650 p
->binding_handle
= dcerpc_pipe_binding_handle(p
);
651 if (p
->binding_handle
== NULL
) {
661 choose the next call id to use
663 static uint32_t next_call_id(struct dcecli_connection
*c
)
666 if (c
->call_id
== 0) {
673 setup for a ndr pull, also setting up any flags from the binding string
675 static struct ndr_pull
*ndr_pull_init_flags(struct dcecli_connection
*c
,
676 DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
)
678 struct ndr_pull
*ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
680 if (ndr
== NULL
) return ndr
;
682 if (c
->flags
& DCERPC_DEBUG_PAD_CHECK
) {
683 ndr
->flags
|= LIBNDR_FLAG_PAD_CHECK
;
686 if (c
->flags
& DCERPC_NDR_REF_ALLOC
) {
687 ndr
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
690 if (c
->flags
& DCERPC_NDR64
) {
691 ndr
->flags
|= LIBNDR_FLAG_NDR64
;
698 parse a data blob into a ncacn_packet structure. This handles both
699 input and output packets
701 static NTSTATUS
ncacn_pull(struct dcecli_connection
*c
, DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
702 struct ncacn_packet
*pkt
)
704 struct ndr_pull
*ndr
;
705 enum ndr_err_code ndr_err
;
707 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
709 return NT_STATUS_NO_MEMORY
;
712 if (! (CVAL(blob
->data
, DCERPC_DREP_OFFSET
) & DCERPC_DREP_LE
)) {
713 ndr
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
716 if (CVAL(blob
->data
, DCERPC_PFC_OFFSET
) & DCERPC_PFC_FLAG_OBJECT_UUID
) {
717 ndr
->flags
|= LIBNDR_FLAG_OBJECT_PRESENT
;
720 ndr_err
= ndr_pull_ncacn_packet(ndr
, NDR_SCALARS
|NDR_BUFFERS
, pkt
);
722 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
723 return ndr_map_error2ntstatus(ndr_err
);
726 if (pkt
->frag_length
!= blob
->length
) {
727 return NT_STATUS_RPC_PROTOCOL_ERROR
;
734 parse the authentication information on a dcerpc response packet
736 static NTSTATUS
ncacn_pull_request_auth(struct dcecli_connection
*c
, TALLOC_CTX
*mem_ctx
,
737 DATA_BLOB
*raw_packet
,
738 struct ncacn_packet
*pkt
)
741 struct dcerpc_auth auth
;
742 uint32_t auth_length
;
744 if (!c
->security_state
.auth_info
||
745 !c
->security_state
.generic_state
) {
749 switch (c
->security_state
.auth_info
->auth_level
) {
750 case DCERPC_AUTH_LEVEL_PRIVACY
:
751 case DCERPC_AUTH_LEVEL_INTEGRITY
:
754 case DCERPC_AUTH_LEVEL_CONNECT
:
755 if (pkt
->auth_length
!= 0) {
759 case DCERPC_AUTH_LEVEL_NONE
:
760 if (pkt
->auth_length
!= 0) {
761 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
766 return NT_STATUS_INVALID_LEVEL
;
769 status
= dcerpc_pull_auth_trailer(pkt
, mem_ctx
,
770 &pkt
->u
.response
.stub_and_verifier
,
771 &auth
, &auth_length
, false);
772 NT_STATUS_NOT_OK_RETURN(status
);
774 pkt
->u
.response
.stub_and_verifier
.length
-= auth_length
;
776 /* check signature or unseal the packet */
777 switch (c
->security_state
.auth_info
->auth_level
) {
778 case DCERPC_AUTH_LEVEL_PRIVACY
:
779 status
= gensec_unseal_packet(c
->security_state
.generic_state
,
780 raw_packet
->data
+ DCERPC_REQUEST_LENGTH
,
781 pkt
->u
.response
.stub_and_verifier
.length
,
783 raw_packet
->length
- auth
.credentials
.length
,
785 memcpy(pkt
->u
.response
.stub_and_verifier
.data
,
786 raw_packet
->data
+ DCERPC_REQUEST_LENGTH
,
787 pkt
->u
.response
.stub_and_verifier
.length
);
790 case DCERPC_AUTH_LEVEL_INTEGRITY
:
791 status
= gensec_check_packet(c
->security_state
.generic_state
,
792 pkt
->u
.response
.stub_and_verifier
.data
,
793 pkt
->u
.response
.stub_and_verifier
.length
,
795 raw_packet
->length
- auth
.credentials
.length
,
799 case DCERPC_AUTH_LEVEL_CONNECT
:
800 /* for now we ignore possible signatures here */
801 status
= NT_STATUS_OK
;
805 status
= NT_STATUS_INVALID_LEVEL
;
809 /* remove the indicated amount of padding */
810 if (pkt
->u
.response
.stub_and_verifier
.length
< auth
.auth_pad_length
) {
811 return NT_STATUS_INFO_LENGTH_MISMATCH
;
813 pkt
->u
.response
.stub_and_verifier
.length
-= auth
.auth_pad_length
;
820 push a dcerpc request packet into a blob, possibly signing it.
822 static NTSTATUS
ncacn_push_request_sign(struct dcecli_connection
*c
,
823 DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
825 struct ncacn_packet
*pkt
)
828 struct ndr_push
*ndr
;
830 size_t payload_length
;
831 enum ndr_err_code ndr_err
;
832 size_t hdr_size
= DCERPC_REQUEST_LENGTH
;
834 /* non-signed packets are simpler */
836 return ncacn_push_auth(blob
, mem_ctx
, pkt
, NULL
);
839 switch (c
->security_state
.auth_info
->auth_level
) {
840 case DCERPC_AUTH_LEVEL_PRIVACY
:
841 case DCERPC_AUTH_LEVEL_INTEGRITY
:
844 case DCERPC_AUTH_LEVEL_CONNECT
:
845 /* TODO: let the gensec mech decide if it wants to generate a signature */
846 return ncacn_push_auth(blob
, mem_ctx
, pkt
, NULL
);
848 case DCERPC_AUTH_LEVEL_NONE
:
849 return ncacn_push_auth(blob
, mem_ctx
, pkt
, NULL
);
852 return NT_STATUS_INVALID_LEVEL
;
855 ndr
= ndr_push_init_ctx(mem_ctx
);
857 return NT_STATUS_NO_MEMORY
;
860 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
861 ndr
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
864 if (c
->flags
& DCERPC_NDR64
) {
865 ndr
->flags
|= LIBNDR_FLAG_NDR64
;
868 if (pkt
->pfc_flags
& DCERPC_PFC_FLAG_OBJECT_UUID
) {
869 ndr
->flags
|= LIBNDR_FLAG_OBJECT_PRESENT
;
873 ndr_err
= ndr_push_ncacn_packet(ndr
, NDR_SCALARS
|NDR_BUFFERS
, pkt
);
874 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
875 return ndr_map_error2ntstatus(ndr_err
);
878 /* pad to 16 byte multiple in the payload portion of the
879 packet. This matches what w2k3 does. Note that we can't use
880 ndr_push_align() as that is relative to the start of the
881 whole packet, whereas w2k8 wants it relative to the start
883 c
->security_state
.auth_info
->auth_pad_length
=
884 (16 - (pkt
->u
.request
.stub_and_verifier
.length
& 15)) & 15;
885 ndr_err
= ndr_push_zero(ndr
, c
->security_state
.auth_info
->auth_pad_length
);
886 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
887 return ndr_map_error2ntstatus(ndr_err
);
890 payload_length
= pkt
->u
.request
.stub_and_verifier
.length
+
891 c
->security_state
.auth_info
->auth_pad_length
;
893 /* we start without signature, it will appended later */
894 c
->security_state
.auth_info
->credentials
= data_blob(NULL
,0);
896 /* add the auth verifier */
897 ndr_err
= ndr_push_dcerpc_auth(ndr
, NDR_SCALARS
|NDR_BUFFERS
, c
->security_state
.auth_info
);
898 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
899 return ndr_map_error2ntstatus(ndr_err
);
902 /* extract the whole packet as a blob */
903 *blob
= ndr_push_blob(ndr
);
906 * Setup the frag and auth length in the packet buffer.
907 * This is needed if the GENSEC mech does AEAD signing
908 * of the packet headers. The signature itself will be
911 dcerpc_set_frag_length(blob
, blob
->length
+ sig_size
);
912 dcerpc_set_auth_length(blob
, sig_size
);
914 /* sign or seal the packet */
915 switch (c
->security_state
.auth_info
->auth_level
) {
916 case DCERPC_AUTH_LEVEL_PRIVACY
:
917 status
= gensec_seal_packet(c
->security_state
.generic_state
,
919 blob
->data
+ hdr_size
,
924 if (!NT_STATUS_IS_OK(status
)) {
929 case DCERPC_AUTH_LEVEL_INTEGRITY
:
930 status
= gensec_sign_packet(c
->security_state
.generic_state
,
932 blob
->data
+ hdr_size
,
937 if (!NT_STATUS_IS_OK(status
)) {
943 status
= NT_STATUS_INVALID_LEVEL
;
947 if (creds2
.length
!= sig_size
) {
948 /* this means the sig_size estimate for the signature
949 was incorrect. We have to correct the packet
950 sizes. That means we could go over the max fragment
952 DEBUG(3,("ncacn_push_request_sign: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n",
953 (unsigned) creds2
.length
,
955 (unsigned) c
->security_state
.auth_info
->auth_pad_length
,
956 (unsigned) pkt
->u
.request
.stub_and_verifier
.length
));
957 dcerpc_set_frag_length(blob
, blob
->length
+ creds2
.length
);
958 dcerpc_set_auth_length(blob
, creds2
.length
);
961 if (!data_blob_append(mem_ctx
, blob
, creds2
.data
, creds2
.length
)) {
962 return NT_STATUS_NO_MEMORY
;
970 fill in the fixed values in a dcerpc header
972 static void init_ncacn_hdr(struct dcecli_connection
*c
, struct ncacn_packet
*pkt
)
975 pkt
->rpc_vers_minor
= 0;
976 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
979 pkt
->drep
[0] = DCERPC_DREP_LE
;
987 map a bind nak reason to a NTSTATUS
989 static NTSTATUS
dcerpc_map_nak_reason(enum dcerpc_bind_nak_reason reason
)
992 case DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED
:
993 return NT_STATUS_REVISION_MISMATCH
;
994 case DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE
:
995 return NT_STATUS_INVALID_PARAMETER
;
999 return NT_STATUS_UNSUCCESSFUL
;
1002 static NTSTATUS
dcerpc_map_ack_reason(const struct dcerpc_ack_ctx
*ack
)
1005 return NT_STATUS_RPC_PROTOCOL_ERROR
;
1008 switch (ack
->result
) {
1009 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK
:
1011 * We have not asked for this...
1013 return NT_STATUS_RPC_PROTOCOL_ERROR
;
1018 switch (ack
->reason
.value
) {
1019 case DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED
:
1020 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX
;
1021 case DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED
:
1022 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX
;
1026 return NT_STATUS_UNSUCCESSFUL
;
1030 remove requests from the pending or queued queues
1032 static int dcerpc_req_dequeue(struct rpc_request
*req
)
1034 switch (req
->state
) {
1035 case RPC_REQUEST_QUEUED
:
1036 DLIST_REMOVE(req
->p
->conn
->request_queue
, req
);
1038 case RPC_REQUEST_PENDING
:
1039 DLIST_REMOVE(req
->p
->conn
->pending
, req
);
1041 case RPC_REQUEST_DONE
:
1049 mark the dcerpc connection dead. All outstanding requests get an error
1051 static void dcerpc_connection_dead(struct dcecli_connection
*conn
, NTSTATUS status
)
1053 if (conn
->dead
) return;
1057 TALLOC_FREE(conn
->io_trigger
);
1058 conn
->io_trigger_pending
= false;
1060 dcerpc_shutdown_pipe(conn
, status
);
1062 /* all pending requests get the error */
1063 while (conn
->pending
) {
1064 struct rpc_request
*req
= conn
->pending
;
1065 dcerpc_req_dequeue(req
);
1066 req
->state
= RPC_REQUEST_DONE
;
1067 req
->status
= status
;
1068 if (req
->async
.callback
) {
1069 req
->async
.callback(req
);
1073 /* all requests, which are not shipped */
1074 while (conn
->request_queue
) {
1075 struct rpc_request
*req
= conn
->request_queue
;
1076 dcerpc_req_dequeue(req
);
1077 req
->state
= RPC_REQUEST_DONE
;
1078 req
->status
= status
;
1079 if (req
->async
.callback
) {
1080 req
->async
.callback(req
);
1084 talloc_set_destructor(conn
, NULL
);
1085 if (conn
->free_skipped
) {
1091 forward declarations of the recv_data handlers for the types of
1092 packets we need to handle
1094 static void dcerpc_request_recv_data(struct dcecli_connection
*c
,
1095 DATA_BLOB
*raw_packet
, struct ncacn_packet
*pkt
);
1098 receive a dcerpc reply from the transport. Here we work out what
1099 type of reply it is (normal request, bind or alter context) and
1100 dispatch to the appropriate handler
1102 static void dcerpc_recv_data(struct dcecli_connection
*conn
, DATA_BLOB
*blob
, NTSTATUS status
)
1104 struct ncacn_packet pkt
;
1110 if (NT_STATUS_IS_OK(status
) && blob
->length
== 0) {
1111 status
= NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
1114 /* the transport may be telling us of a severe error, such as
1116 if (!NT_STATUS_IS_OK(status
)) {
1117 data_blob_free(blob
);
1118 dcerpc_connection_dead(conn
, status
);
1122 /* parse the basic packet to work out what type of response this is */
1123 status
= ncacn_pull(conn
, blob
, blob
->data
, &pkt
);
1124 if (!NT_STATUS_IS_OK(status
)) {
1125 data_blob_free(blob
);
1126 dcerpc_connection_dead(conn
, status
);
1130 dcerpc_request_recv_data(conn
, blob
, &pkt
);
1134 handle timeouts of individual dcerpc requests
1136 static void dcerpc_timeout_handler(struct tevent_context
*ev
, struct tevent_timer
*te
,
1137 struct timeval t
, void *private_data
)
1139 struct rpc_request
*req
= talloc_get_type(private_data
, struct rpc_request
);
1141 if (req
->ignore_timeout
) {
1142 dcerpc_req_dequeue(req
);
1143 req
->state
= RPC_REQUEST_DONE
;
1144 req
->status
= NT_STATUS_IO_TIMEOUT
;
1145 if (req
->async
.callback
) {
1146 req
->async
.callback(req
);
1151 dcerpc_connection_dead(req
->p
->conn
, NT_STATUS_IO_TIMEOUT
);
1154 struct dcerpc_bind_state
{
1155 struct tevent_context
*ev
;
1156 struct dcerpc_pipe
*p
;
1159 static void dcerpc_bind_fail_handler(struct rpc_request
*subreq
);
1160 static void dcerpc_bind_recv_handler(struct rpc_request
*subreq
,
1161 DATA_BLOB
*raw_packet
,
1162 struct ncacn_packet
*pkt
);
1164 struct tevent_req
*dcerpc_bind_send(TALLOC_CTX
*mem_ctx
,
1165 struct tevent_context
*ev
,
1166 struct dcerpc_pipe
*p
,
1167 const struct ndr_syntax_id
*syntax
,
1168 const struct ndr_syntax_id
*transfer_syntax
)
1170 struct tevent_req
*req
;
1171 struct dcerpc_bind_state
*state
;
1172 struct ncacn_packet pkt
;
1175 struct rpc_request
*subreq
;
1178 req
= tevent_req_create(mem_ctx
, &state
,
1179 struct dcerpc_bind_state
);
1187 p
->syntax
= *syntax
;
1188 p
->transfer_syntax
= *transfer_syntax
;
1190 flags
= dcerpc_binding_get_flags(p
->binding
);
1192 init_ncacn_hdr(p
->conn
, &pkt
);
1194 pkt
.ptype
= DCERPC_PKT_BIND
;
1195 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
1196 pkt
.call_id
= p
->conn
->call_id
;
1197 pkt
.auth_length
= 0;
1199 if (flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
1200 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
1203 if (p
->conn
->flags
& DCERPC_PROPOSE_HEADER_SIGNING
) {
1204 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
;
1207 pkt
.u
.bind
.max_xmit_frag
= p
->conn
->srv_max_xmit_frag
;
1208 pkt
.u
.bind
.max_recv_frag
= p
->conn
->srv_max_recv_frag
;
1209 pkt
.u
.bind
.assoc_group_id
= dcerpc_binding_get_assoc_group_id(p
->binding
);
1210 pkt
.u
.bind
.num_contexts
= 1;
1211 pkt
.u
.bind
.ctx_list
= talloc_array(mem_ctx
, struct dcerpc_ctx_list
, 1);
1212 if (tevent_req_nomem(pkt
.u
.bind
.ctx_list
, req
)) {
1213 return tevent_req_post(req
, ev
);
1215 pkt
.u
.bind
.ctx_list
[0].context_id
= p
->context_id
;
1216 pkt
.u
.bind
.ctx_list
[0].num_transfer_syntaxes
= 1;
1217 pkt
.u
.bind
.ctx_list
[0].abstract_syntax
= p
->syntax
;
1218 pkt
.u
.bind
.ctx_list
[0].transfer_syntaxes
= &p
->transfer_syntax
;
1219 pkt
.u
.bind
.auth_info
= data_blob(NULL
, 0);
1221 /* construct the NDR form of the packet */
1222 status
= ncacn_push_auth(&blob
, state
, &pkt
,
1223 p
->conn
->security_state
.auth_info
);
1224 if (tevent_req_nterror(req
, status
)) {
1225 return tevent_req_post(req
, ev
);
1229 * we allocate a dcerpc_request so we can be in the same
1230 * request queue as normal requests
1232 subreq
= talloc_zero(state
, struct rpc_request
);
1233 if (tevent_req_nomem(subreq
, req
)) {
1234 return tevent_req_post(req
, ev
);
1237 subreq
->state
= RPC_REQUEST_PENDING
;
1238 subreq
->call_id
= pkt
.call_id
;
1239 subreq
->async
.private_data
= req
;
1240 subreq
->async
.callback
= dcerpc_bind_fail_handler
;
1242 subreq
->recv_handler
= dcerpc_bind_recv_handler
;
1243 DLIST_ADD_END(p
->conn
->pending
, subreq
, struct rpc_request
*);
1244 talloc_set_destructor(subreq
, dcerpc_req_dequeue
);
1246 status
= dcerpc_send_request(p
->conn
, &blob
, true);
1247 if (tevent_req_nterror(req
, status
)) {
1248 return tevent_req_post(req
, ev
);
1251 tevent_add_timer(ev
, subreq
,
1252 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT
, 0),
1253 dcerpc_timeout_handler
, subreq
);
1258 static void dcerpc_bind_fail_handler(struct rpc_request
*subreq
)
1260 struct tevent_req
*req
=
1261 talloc_get_type_abort(subreq
->async
.private_data
,
1263 struct dcerpc_bind_state
*state
=
1264 tevent_req_data(req
,
1265 struct dcerpc_bind_state
);
1266 NTSTATUS status
= subreq
->status
;
1268 TALLOC_FREE(subreq
);
1271 * We trigger the callback in the next event run
1272 * because the code in this file might trigger
1273 * multiple request callbacks from within a single
1276 * In order to avoid segfaults from within
1277 * dcerpc_connection_dead() we call
1278 * tevent_req_defer_callback().
1280 tevent_req_defer_callback(req
, state
->ev
);
1282 tevent_req_nterror(req
, status
);
1285 static void dcerpc_bind_recv_handler(struct rpc_request
*subreq
,
1286 DATA_BLOB
*raw_packet
,
1287 struct ncacn_packet
*pkt
)
1289 struct tevent_req
*req
=
1290 talloc_get_type_abort(subreq
->async
.private_data
,
1292 struct dcerpc_bind_state
*state
=
1293 tevent_req_data(req
,
1294 struct dcerpc_bind_state
);
1295 struct dcecli_connection
*conn
= state
->p
->conn
;
1296 struct dcerpc_binding
*b
= NULL
;
1301 * Note that pkt is allocated under raw_packet->data,
1302 * while raw_packet->data is a child of subreq.
1304 talloc_steal(state
, raw_packet
->data
);
1305 TALLOC_FREE(subreq
);
1308 * We trigger the callback in the next event run
1309 * because the code in this file might trigger
1310 * multiple request callbacks from within a single
1313 * In order to avoid segfaults from within
1314 * dcerpc_connection_dead() we call
1315 * tevent_req_defer_callback().
1317 tevent_req_defer_callback(req
, state
->ev
);
1319 if (pkt
->ptype
== DCERPC_PKT_BIND_NAK
) {
1320 status
= dcerpc_map_nak_reason(pkt
->u
.bind_nak
.reject_reason
);
1322 DEBUG(2,("dcerpc: bind_nak reason %d - %s\n",
1323 pkt
->u
.bind_nak
.reject_reason
, nt_errstr(status
)));
1325 tevent_req_nterror(req
, status
);
1329 if ((pkt
->ptype
!= DCERPC_PKT_BIND_ACK
) ||
1330 (pkt
->u
.bind_ack
.num_results
== 0) ||
1331 (pkt
->u
.bind_ack
.ctx_list
[0].result
!= 0)) {
1332 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
1333 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
1338 * DCE-RPC 1.1 (c706) specifies
1339 * CONST_MUST_RCV_FRAG_SIZE as 1432
1341 if (pkt
->u
.bind_ack
.max_xmit_frag
< 1432) {
1342 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
1343 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
1346 if (pkt
->u
.bind_ack
.max_recv_frag
< 1432) {
1347 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
1348 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
1351 conn
->srv_max_xmit_frag
= MIN(conn
->srv_max_xmit_frag
,
1352 pkt
->u
.bind_ack
.max_xmit_frag
);
1353 conn
->srv_max_recv_frag
= MIN(conn
->srv_max_recv_frag
,
1354 pkt
->u
.bind_ack
.max_recv_frag
);
1356 flags
= dcerpc_binding_get_flags(state
->p
->binding
);
1358 if ((flags
& DCERPC_CONCURRENT_MULTIPLEX
) &&
1359 (pkt
->pfc_flags
& DCERPC_PFC_FLAG_CONC_MPX
)) {
1360 conn
->flags
|= DCERPC_CONCURRENT_MULTIPLEX
;
1363 if ((conn
->flags
& DCERPC_PROPOSE_HEADER_SIGNING
) &&
1364 (pkt
->pfc_flags
& DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN
)) {
1365 conn
->flags
|= DCERPC_HEADER_SIGNING
;
1368 /* the bind_ack might contain a reply set of credentials */
1369 if (conn
->security_state
.auth_info
&& pkt
->u
.bind_ack
.auth_info
.length
) {
1370 uint32_t auth_length
;
1372 status
= dcerpc_pull_auth_trailer(pkt
, conn
, &pkt
->u
.bind_ack
.auth_info
,
1373 conn
->security_state
.auth_info
, &auth_length
, true);
1374 if (tevent_req_nterror(req
, status
)) {
1380 * We're the owner of the binding, so we're allowed to modify it.
1382 b
= discard_const_p(struct dcerpc_binding
, state
->p
->binding
);
1383 status
= dcerpc_binding_set_assoc_group_id(b
,
1384 pkt
->u
.bind_ack
.assoc_group_id
);
1385 if (tevent_req_nterror(req
, status
)) {
1389 tevent_req_done(req
);
1392 NTSTATUS
dcerpc_bind_recv(struct tevent_req
*req
)
1394 return tevent_req_simple_recv_ntstatus(req
);
1398 perform a continued bind (and auth3)
1400 NTSTATUS
dcerpc_auth3(struct dcerpc_pipe
*p
,
1401 TALLOC_CTX
*mem_ctx
)
1403 struct ncacn_packet pkt
;
1408 flags
= dcerpc_binding_get_flags(p
->binding
);
1410 init_ncacn_hdr(p
->conn
, &pkt
);
1412 pkt
.ptype
= DCERPC_PKT_AUTH3
;
1413 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
1414 pkt
.call_id
= next_call_id(p
->conn
);
1415 pkt
.auth_length
= 0;
1416 pkt
.u
.auth3
.auth_info
= data_blob(NULL
, 0);
1418 if (flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
1419 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
1422 /* construct the NDR form of the packet */
1423 status
= ncacn_push_auth(&blob
, mem_ctx
,
1425 p
->conn
->security_state
.auth_info
);
1426 if (!NT_STATUS_IS_OK(status
)) {
1430 /* send it on its way */
1431 status
= dcerpc_send_request(p
->conn
, &blob
, false);
1432 if (!NT_STATUS_IS_OK(status
)) {
1436 return NT_STATUS_OK
;
1441 process a fragment received from the transport layer during a
1444 This function frees the data
1446 static void dcerpc_request_recv_data(struct dcecli_connection
*c
,
1447 DATA_BLOB
*raw_packet
, struct ncacn_packet
*pkt
)
1449 struct rpc_request
*req
;
1450 unsigned int length
;
1451 NTSTATUS status
= NT_STATUS_OK
;
1454 if this is an authenticated connection then parse and check
1455 the auth info. We have to do this before finding the
1456 matching packet, as the request structure might have been
1457 removed due to a timeout, but if it has been we still need
1458 to run the auth routines so that we don't get the sign/seal
1459 info out of step with the server
1461 if (c
->security_state
.auth_info
&& c
->security_state
.generic_state
&&
1462 pkt
->ptype
== DCERPC_PKT_RESPONSE
) {
1463 status
= ncacn_pull_request_auth(c
, raw_packet
->data
, raw_packet
, pkt
);
1466 /* find the matching request */
1467 for (req
=c
->pending
;req
;req
=req
->next
) {
1468 if (pkt
->call_id
== req
->call_id
) break;
1472 /* useful for testing certain vendors RPC servers */
1473 if (req
== NULL
&& c
->pending
&& pkt
->call_id
== 0) {
1474 DEBUG(0,("HACK FOR INCORRECT CALL ID\n"));
1480 DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt
->call_id
));
1481 data_blob_free(raw_packet
);
1485 talloc_steal(req
, raw_packet
->data
);
1487 if (req
->recv_handler
!= NULL
) {
1488 dcerpc_req_dequeue(req
);
1489 req
->state
= RPC_REQUEST_DONE
;
1492 * We have to look at shipping further requests before calling
1493 * the async function, that one might close the pipe
1495 dcerpc_schedule_io_trigger(c
);
1497 req
->recv_handler(req
, raw_packet
, pkt
);
1501 if (pkt
->ptype
== DCERPC_PKT_FAULT
) {
1502 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c
, pkt
->u
.fault
.status
)));
1503 req
->fault_code
= pkt
->u
.fault
.status
;
1504 req
->status
= NT_STATUS_NET_WRITE_FAULT
;
1508 if (pkt
->ptype
!= DCERPC_PKT_RESPONSE
) {
1509 DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
1511 req
->fault_code
= DCERPC_FAULT_OTHER
;
1512 req
->status
= NT_STATUS_NET_WRITE_FAULT
;
1516 /* now check the status from the auth routines, and if it failed then fail
1517 this request accordingly */
1518 if (!NT_STATUS_IS_OK(status
)) {
1519 req
->status
= status
;
1523 length
= pkt
->u
.response
.stub_and_verifier
.length
;
1526 req
->payload
.data
= talloc_realloc(req
,
1529 req
->payload
.length
+ length
);
1530 if (!req
->payload
.data
) {
1531 req
->status
= NT_STATUS_NO_MEMORY
;
1534 memcpy(req
->payload
.data
+req
->payload
.length
,
1535 pkt
->u
.response
.stub_and_verifier
.data
, length
);
1536 req
->payload
.length
+= length
;
1539 if (!(pkt
->pfc_flags
& DCERPC_PFC_FLAG_LAST
)) {
1540 data_blob_free(raw_packet
);
1541 dcerpc_send_read(c
);
1545 if (!(pkt
->drep
[0] & DCERPC_DREP_LE
)) {
1546 req
->flags
|= DCERPC_PULL_BIGENDIAN
;
1548 req
->flags
&= ~DCERPC_PULL_BIGENDIAN
;
1552 data_blob_free(raw_packet
);
1554 /* we've got the full payload */
1555 dcerpc_req_dequeue(req
);
1556 req
->state
= RPC_REQUEST_DONE
;
1559 * We have to look at shipping further requests before calling
1560 * the async function, that one might close the pipe
1562 dcerpc_schedule_io_trigger(c
);
1564 if (req
->async
.callback
) {
1565 req
->async
.callback(req
);
1570 perform the send side of a async dcerpc request
1572 static struct rpc_request
*dcerpc_request_send(TALLOC_CTX
*mem_ctx
,
1573 struct dcerpc_pipe
*p
,
1574 const struct GUID
*object
,
1576 DATA_BLOB
*stub_data
)
1578 struct rpc_request
*req
;
1580 req
= talloc_zero(mem_ctx
, struct rpc_request
);
1586 req
->call_id
= next_call_id(p
->conn
);
1587 req
->state
= RPC_REQUEST_QUEUED
;
1589 if (object
!= NULL
) {
1590 req
->object
= (struct GUID
*)talloc_memdup(req
, (const void *)object
, sizeof(*object
));
1591 if (req
->object
== NULL
) {
1598 req
->request_data
.length
= stub_data
->length
;
1599 req
->request_data
.data
= stub_data
->data
;
1601 DLIST_ADD_END(p
->conn
->request_queue
, req
, struct rpc_request
*);
1602 talloc_set_destructor(req
, dcerpc_req_dequeue
);
1604 dcerpc_schedule_io_trigger(p
->conn
);
1606 if (p
->request_timeout
) {
1607 tevent_add_timer(p
->conn
->event_ctx
, req
,
1608 timeval_current_ofs(p
->request_timeout
, 0),
1609 dcerpc_timeout_handler
, req
);
1616 Send a request using the transport
1619 static void dcerpc_ship_next_request(struct dcecli_connection
*c
)
1621 struct rpc_request
*req
;
1622 struct dcerpc_pipe
*p
;
1623 DATA_BLOB
*stub_data
;
1624 struct ncacn_packet pkt
;
1626 uint32_t remaining
, chunk_size
;
1627 bool first_packet
= true;
1628 size_t sig_size
= 0;
1629 bool need_async
= false;
1630 bool can_async
= true;
1632 req
= c
->request_queue
;
1638 stub_data
= &req
->request_data
;
1644 if (c
->security_state
.auth_info
&&
1645 c
->security_state
.generic_state
)
1647 struct gensec_security
*gensec
= c
->security_state
.generic_state
;
1649 switch (c
->security_state
.auth_info
->auth_level
) {
1650 case DCERPC_AUTH_LEVEL_PRIVACY
:
1651 case DCERPC_AUTH_LEVEL_INTEGRITY
:
1652 can_async
= gensec_have_feature(gensec
,
1653 GENSEC_FEATURE_ASYNC_REPLIES
);
1655 case DCERPC_AUTH_LEVEL_CONNECT
:
1656 case DCERPC_AUTH_LEVEL_NONE
:
1665 if (need_async
&& !can_async
) {
1666 req
->wait_for_sync
= true;
1670 DLIST_REMOVE(c
->request_queue
, req
);
1671 DLIST_ADD(c
->pending
, req
);
1672 req
->state
= RPC_REQUEST_PENDING
;
1674 init_ncacn_hdr(p
->conn
, &pkt
);
1676 remaining
= stub_data
->length
;
1678 /* we can write a full max_recv_frag size, minus the dcerpc
1679 request header size */
1680 chunk_size
= p
->conn
->srv_max_recv_frag
;
1681 chunk_size
-= DCERPC_REQUEST_LENGTH
;
1682 if (c
->security_state
.auth_info
&&
1683 c
->security_state
.generic_state
) {
1684 sig_size
= gensec_sig_size(c
->security_state
.generic_state
,
1685 p
->conn
->srv_max_recv_frag
);
1687 chunk_size
-= DCERPC_AUTH_TRAILER_LENGTH
;
1688 chunk_size
-= sig_size
;
1691 chunk_size
-= (chunk_size
% 16);
1693 pkt
.ptype
= DCERPC_PKT_REQUEST
;
1694 pkt
.call_id
= req
->call_id
;
1695 pkt
.auth_length
= 0;
1697 pkt
.u
.request
.context_id
= p
->context_id
;
1698 pkt
.u
.request
.opnum
= req
->opnum
;
1701 pkt
.u
.request
.object
.object
= *req
->object
;
1702 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_OBJECT_UUID
;
1703 chunk_size
-= ndr_size_GUID(req
->object
,0);
1706 /* we send a series of pdus without waiting for a reply */
1707 while (remaining
> 0 || first_packet
) {
1708 uint32_t chunk
= MIN(chunk_size
, remaining
);
1709 bool last_frag
= false;
1710 bool do_trans
= false;
1712 first_packet
= false;
1713 pkt
.pfc_flags
&= ~(DCERPC_PFC_FLAG_FIRST
|DCERPC_PFC_FLAG_LAST
);
1715 if (remaining
== stub_data
->length
) {
1716 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_FIRST
;
1718 if (chunk
== remaining
) {
1719 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_LAST
;
1723 pkt
.u
.request
.alloc_hint
= remaining
;
1724 pkt
.u
.request
.stub_and_verifier
.data
= stub_data
->data
+
1725 (stub_data
->length
- remaining
);
1726 pkt
.u
.request
.stub_and_verifier
.length
= chunk
;
1728 req
->status
= ncacn_push_request_sign(p
->conn
, &blob
, req
, sig_size
, &pkt
);
1729 if (!NT_STATUS_IS_OK(req
->status
)) {
1730 req
->state
= RPC_REQUEST_DONE
;
1731 DLIST_REMOVE(p
->conn
->pending
, req
);
1735 if (last_frag
&& !need_async
) {
1739 req
->status
= dcerpc_send_request(p
->conn
, &blob
, do_trans
);
1740 if (!NT_STATUS_IS_OK(req
->status
)) {
1741 req
->state
= RPC_REQUEST_DONE
;
1742 DLIST_REMOVE(p
->conn
->pending
, req
);
1746 if (last_frag
&& !do_trans
) {
1747 req
->status
= dcerpc_send_read(p
->conn
);
1748 if (!NT_STATUS_IS_OK(req
->status
)) {
1749 req
->state
= RPC_REQUEST_DONE
;
1750 DLIST_REMOVE(p
->conn
->pending
, req
);
1759 static void dcerpc_io_trigger(struct tevent_context
*ctx
,
1760 struct tevent_immediate
*im
,
1763 struct dcecli_connection
*c
=
1764 talloc_get_type_abort(private_data
,
1765 struct dcecli_connection
);
1767 c
->io_trigger_pending
= false;
1769 dcerpc_schedule_io_trigger(c
);
1771 dcerpc_ship_next_request(c
);
1774 static void dcerpc_schedule_io_trigger(struct dcecli_connection
*c
)
1780 if (c
->request_queue
== NULL
) {
1784 if (c
->request_queue
->wait_for_sync
&& c
->pending
) {
1788 if (c
->io_trigger_pending
) {
1792 c
->io_trigger_pending
= true;
1794 tevent_schedule_immediate(c
->io_trigger
,
1801 perform the receive side of a async dcerpc request
1803 static NTSTATUS
dcerpc_request_recv(struct rpc_request
*req
,
1804 TALLOC_CTX
*mem_ctx
,
1805 DATA_BLOB
*stub_data
)
1809 while (req
->state
!= RPC_REQUEST_DONE
) {
1810 struct tevent_context
*ctx
= req
->p
->conn
->event_ctx
;
1811 if (tevent_loop_once(ctx
) != 0) {
1812 return NT_STATUS_CONNECTION_DISCONNECTED
;
1815 *stub_data
= req
->payload
;
1816 status
= req
->status
;
1817 if (stub_data
->data
) {
1818 stub_data
->data
= talloc_steal(mem_ctx
, stub_data
->data
);
1820 if (NT_STATUS_EQUAL(status
, NT_STATUS_NET_WRITE_FAULT
)) {
1821 req
->p
->last_fault_code
= req
->fault_code
;
1823 talloc_unlink(talloc_parent(req
), req
);
1828 this is a paranoid NDR validator. For every packet we push onto the wire
1829 we pull it back again, then push it again. Then we compare the raw NDR data
1830 for that to the NDR we initially generated. If they don't match then we know
1831 we must have a bug in either the pull or push side of our code
1833 static NTSTATUS
dcerpc_ndr_validate_in(struct dcecli_connection
*c
,
1834 TALLOC_CTX
*mem_ctx
,
1837 ndr_push_flags_fn_t ndr_push
,
1838 ndr_pull_flags_fn_t ndr_pull
)
1841 struct ndr_pull
*pull
;
1842 struct ndr_push
*push
;
1844 enum ndr_err_code ndr_err
;
1846 st
= talloc_size(mem_ctx
, struct_size
);
1848 return NT_STATUS_NO_MEMORY
;
1851 pull
= ndr_pull_init_flags(c
, &blob
, mem_ctx
);
1853 return NT_STATUS_NO_MEMORY
;
1855 pull
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
1857 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
1858 pull
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
1861 if (c
->flags
& DCERPC_NDR64
) {
1862 pull
->flags
|= LIBNDR_FLAG_NDR64
;
1865 ndr_err
= ndr_pull(pull
, NDR_IN
, st
);
1866 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1867 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1868 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
1869 "failed input validation pull - %s",
1871 return ndr_map_error2ntstatus(ndr_err
);
1874 push
= ndr_push_init_ctx(mem_ctx
);
1876 return NT_STATUS_NO_MEMORY
;
1879 if (c
->flags
& DCERPC_PUSH_BIGENDIAN
) {
1880 push
->flags
|= LIBNDR_FLAG_BIGENDIAN
;
1883 if (c
->flags
& DCERPC_NDR64
) {
1884 push
->flags
|= LIBNDR_FLAG_NDR64
;
1887 ndr_err
= ndr_push(push
, NDR_IN
, st
);
1888 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1889 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1890 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
1891 "failed input validation push - %s",
1893 return ndr_map_error2ntstatus(ndr_err
);
1896 blob2
= ndr_push_blob(push
);
1898 if (data_blob_cmp(&blob
, &blob2
) != 0) {
1899 DEBUG(3,("original:\n"));
1900 dump_data(3, blob
.data
, blob
.length
);
1901 DEBUG(3,("secondary:\n"));
1902 dump_data(3, blob2
.data
, blob2
.length
);
1903 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
1904 "failed input validation blobs doesn't match");
1905 return ndr_map_error2ntstatus(ndr_err
);
1908 return NT_STATUS_OK
;
1912 this is a paranoid NDR input validator. For every packet we pull
1913 from the wire we push it back again then pull and push it
1914 again. Then we compare the raw NDR data for that to the NDR we
1915 initially generated. If they don't match then we know we must have a
1916 bug in either the pull or push side of our code
1918 static NTSTATUS
dcerpc_ndr_validate_out(struct dcecli_connection
*c
,
1919 struct ndr_pull
*pull_in
,
1922 ndr_push_flags_fn_t ndr_push
,
1923 ndr_pull_flags_fn_t ndr_pull
,
1924 ndr_print_function_t ndr_print
)
1927 struct ndr_pull
*pull
;
1928 struct ndr_push
*push
;
1929 DATA_BLOB blob
, blob2
;
1930 TALLOC_CTX
*mem_ctx
= pull_in
;
1932 enum ndr_err_code ndr_err
;
1934 st
= talloc_size(mem_ctx
, struct_size
);
1936 return NT_STATUS_NO_MEMORY
;
1938 memcpy(st
, struct_ptr
, struct_size
);
1940 push
= ndr_push_init_ctx(mem_ctx
);
1942 return NT_STATUS_NO_MEMORY
;
1945 ndr_err
= ndr_push(push
, NDR_OUT
, struct_ptr
);
1946 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1947 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1948 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
1949 "failed output validation push - %s",
1951 return ndr_map_error2ntstatus(ndr_err
);
1954 blob
= ndr_push_blob(push
);
1956 pull
= ndr_pull_init_flags(c
, &blob
, mem_ctx
);
1958 return NT_STATUS_NO_MEMORY
;
1961 pull
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
1962 ndr_err
= ndr_pull(pull
, NDR_OUT
, st
);
1963 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1964 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1965 ndr_err
= ndr_pull_error(pull
, NDR_ERR_VALIDATE
,
1966 "failed output validation pull - %s",
1968 return ndr_map_error2ntstatus(ndr_err
);
1971 push
= ndr_push_init_ctx(mem_ctx
);
1973 return NT_STATUS_NO_MEMORY
;
1976 ndr_err
= ndr_push(push
, NDR_OUT
, st
);
1977 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1978 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
1979 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
1980 "failed output validation push2 - %s",
1982 return ndr_map_error2ntstatus(ndr_err
);
1985 blob2
= ndr_push_blob(push
);
1987 if (data_blob_cmp(&blob
, &blob2
) != 0) {
1988 DEBUG(3,("original:\n"));
1989 dump_data(3, blob
.data
, blob
.length
);
1990 DEBUG(3,("secondary:\n"));
1991 dump_data(3, blob2
.data
, blob2
.length
);
1992 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
1993 "failed output validation blobs doesn't match");
1994 return ndr_map_error2ntstatus(ndr_err
);
1997 /* this checks the printed forms of the two structures, which effectively
1998 tests all of the value() attributes */
1999 s1
= ndr_print_function_string(mem_ctx
, ndr_print
, "VALIDATE",
2000 NDR_OUT
, struct_ptr
);
2001 s2
= ndr_print_function_string(mem_ctx
, ndr_print
, "VALIDATE",
2003 if (strcmp(s1
, s2
) != 0) {
2005 DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1
, s2
));
2007 /* this is sometimes useful */
2008 printf("VALIDATE ERROR\n");
2009 file_save("wire.dat", s1
, strlen(s1
));
2010 file_save("gen.dat", s2
, strlen(s2
));
2011 system("diff -u wire.dat gen.dat");
2013 ndr_err
= ndr_push_error(push
, NDR_ERR_VALIDATE
,
2014 "failed output validation strings doesn't match");
2015 return ndr_map_error2ntstatus(ndr_err
);
2018 return NT_STATUS_OK
;
2022 a useful function for retrieving the server name we connected to
2024 _PUBLIC_
const char *dcerpc_server_name(struct dcerpc_pipe
*p
)
2026 return p
->conn
? p
->conn
->server_name
: NULL
;
2031 get the dcerpc auth_level for a open connection
2033 uint32_t dcerpc_auth_level(struct dcecli_connection
*c
)
2037 if (c
->flags
& DCERPC_SEAL
) {
2038 auth_level
= DCERPC_AUTH_LEVEL_PRIVACY
;
2039 } else if (c
->flags
& DCERPC_SIGN
) {
2040 auth_level
= DCERPC_AUTH_LEVEL_INTEGRITY
;
2041 } else if (c
->flags
& DCERPC_CONNECT
) {
2042 auth_level
= DCERPC_AUTH_LEVEL_CONNECT
;
2044 auth_level
= DCERPC_AUTH_LEVEL_NONE
;
2049 struct dcerpc_alter_context_state
{
2050 struct tevent_context
*ev
;
2051 struct dcerpc_pipe
*p
;
2054 static void dcerpc_alter_context_fail_handler(struct rpc_request
*subreq
);
2055 static void dcerpc_alter_context_recv_handler(struct rpc_request
*req
,
2056 DATA_BLOB
*raw_packet
,
2057 struct ncacn_packet
*pkt
);
2059 struct tevent_req
*dcerpc_alter_context_send(TALLOC_CTX
*mem_ctx
,
2060 struct tevent_context
*ev
,
2061 struct dcerpc_pipe
*p
,
2062 const struct ndr_syntax_id
*syntax
,
2063 const struct ndr_syntax_id
*transfer_syntax
)
2065 struct tevent_req
*req
;
2066 struct dcerpc_alter_context_state
*state
;
2067 struct ncacn_packet pkt
;
2070 struct rpc_request
*subreq
;
2073 req
= tevent_req_create(mem_ctx
, &state
,
2074 struct dcerpc_alter_context_state
);
2082 p
->syntax
= *syntax
;
2083 p
->transfer_syntax
= *transfer_syntax
;
2085 flags
= dcerpc_binding_get_flags(p
->binding
);
2087 init_ncacn_hdr(p
->conn
, &pkt
);
2089 pkt
.ptype
= DCERPC_PKT_ALTER
;
2090 pkt
.pfc_flags
= DCERPC_PFC_FLAG_FIRST
| DCERPC_PFC_FLAG_LAST
;
2091 pkt
.call_id
= p
->conn
->call_id
;
2092 pkt
.auth_length
= 0;
2094 if (flags
& DCERPC_CONCURRENT_MULTIPLEX
) {
2095 pkt
.pfc_flags
|= DCERPC_PFC_FLAG_CONC_MPX
;
2098 pkt
.u
.alter
.max_xmit_frag
= p
->conn
->srv_max_xmit_frag
;
2099 pkt
.u
.alter
.max_recv_frag
= p
->conn
->srv_max_recv_frag
;
2100 pkt
.u
.alter
.assoc_group_id
= dcerpc_binding_get_assoc_group_id(p
->binding
);
2101 pkt
.u
.alter
.num_contexts
= 1;
2102 pkt
.u
.alter
.ctx_list
= talloc_array(state
, struct dcerpc_ctx_list
, 1);
2103 if (tevent_req_nomem(pkt
.u
.alter
.ctx_list
, req
)) {
2104 return tevent_req_post(req
, ev
);
2106 pkt
.u
.alter
.ctx_list
[0].context_id
= p
->context_id
;
2107 pkt
.u
.alter
.ctx_list
[0].num_transfer_syntaxes
= 1;
2108 pkt
.u
.alter
.ctx_list
[0].abstract_syntax
= p
->syntax
;
2109 pkt
.u
.alter
.ctx_list
[0].transfer_syntaxes
= &p
->transfer_syntax
;
2110 pkt
.u
.alter
.auth_info
= data_blob(NULL
, 0);
2112 /* construct the NDR form of the packet */
2113 status
= ncacn_push_auth(&blob
, state
, &pkt
,
2114 p
->conn
->security_state
.auth_info
);
2115 if (tevent_req_nterror(req
, status
)) {
2116 return tevent_req_post(req
, ev
);
2120 * we allocate a dcerpc_request so we can be in the same
2121 * request queue as normal requests
2123 subreq
= talloc_zero(state
, struct rpc_request
);
2124 if (tevent_req_nomem(subreq
, req
)) {
2125 return tevent_req_post(req
, ev
);
2128 subreq
->state
= RPC_REQUEST_PENDING
;
2129 subreq
->call_id
= pkt
.call_id
;
2130 subreq
->async
.private_data
= req
;
2131 subreq
->async
.callback
= dcerpc_alter_context_fail_handler
;
2133 subreq
->recv_handler
= dcerpc_alter_context_recv_handler
;
2134 DLIST_ADD_END(p
->conn
->pending
, subreq
, struct rpc_request
*);
2135 talloc_set_destructor(subreq
, dcerpc_req_dequeue
);
2137 status
= dcerpc_send_request(p
->conn
, &blob
, true);
2138 if (tevent_req_nterror(req
, status
)) {
2139 return tevent_req_post(req
, ev
);
2142 tevent_add_timer(ev
, subreq
,
2143 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT
, 0),
2144 dcerpc_timeout_handler
, subreq
);
2149 static void dcerpc_alter_context_fail_handler(struct rpc_request
*subreq
)
2151 struct tevent_req
*req
=
2152 talloc_get_type_abort(subreq
->async
.private_data
,
2154 struct dcerpc_alter_context_state
*state
=
2155 tevent_req_data(req
,
2156 struct dcerpc_alter_context_state
);
2157 NTSTATUS status
= subreq
->status
;
2159 TALLOC_FREE(subreq
);
2162 * We trigger the callback in the next event run
2163 * because the code in this file might trigger
2164 * multiple request callbacks from within a single
2167 * In order to avoid segfaults from within
2168 * dcerpc_connection_dead() we call
2169 * tevent_req_defer_callback().
2171 tevent_req_defer_callback(req
, state
->ev
);
2173 tevent_req_nterror(req
, status
);
2176 static void dcerpc_alter_context_recv_handler(struct rpc_request
*subreq
,
2177 DATA_BLOB
*raw_packet
,
2178 struct ncacn_packet
*pkt
)
2180 struct tevent_req
*req
=
2181 talloc_get_type_abort(subreq
->async
.private_data
,
2183 struct dcerpc_alter_context_state
*state
=
2184 tevent_req_data(req
,
2185 struct dcerpc_alter_context_state
);
2186 struct dcecli_connection
*conn
= state
->p
->conn
;
2190 * Note that pkt is allocated under raw_packet->data,
2191 * while raw_packet->data is a child of subreq.
2193 talloc_steal(state
, raw_packet
->data
);
2194 TALLOC_FREE(subreq
);
2197 * We trigger the callback in the next event run
2198 * because the code in this file might trigger
2199 * multiple request callbacks from within a single
2202 * In order to avoid segfaults from within
2203 * dcerpc_connection_dead() we call
2204 * tevent_req_defer_callback().
2206 tevent_req_defer_callback(req
, state
->ev
);
2208 if (pkt
->ptype
== DCERPC_PKT_ALTER_RESP
&&
2209 pkt
->u
.alter_resp
.num_results
== 1 &&
2210 pkt
->u
.alter_resp
.ctx_list
[0].result
!= 0) {
2211 status
= dcerpc_map_ack_reason(&pkt
->u
.alter_resp
.ctx_list
[0]);
2212 DEBUG(2,("dcerpc: alter_resp failed - reason %d - %s\n",
2213 pkt
->u
.alter_resp
.ctx_list
[0].reason
.value
,
2214 nt_errstr(status
)));
2215 tevent_req_nterror(req
, status
);
2219 if (pkt
->ptype
== DCERPC_PKT_FAULT
) {
2220 DEBUG(5,("dcerpc: alter_resp - rpc fault: %s\n",
2221 dcerpc_errstr(state
, pkt
->u
.fault
.status
)));
2222 if (pkt
->u
.fault
.status
== DCERPC_FAULT_ACCESS_DENIED
) {
2223 state
->p
->last_fault_code
= pkt
->u
.fault
.status
;
2224 tevent_req_nterror(req
, NT_STATUS_LOGON_FAILURE
);
2226 state
->p
->last_fault_code
= pkt
->u
.fault
.status
;
2227 status
= dcerpc_fault_to_nt_status(pkt
->u
.fault
.status
);
2228 tevent_req_nterror(req
, status
);
2233 if (pkt
->ptype
!= DCERPC_PKT_ALTER_RESP
||
2234 pkt
->u
.alter_resp
.num_results
== 0 ||
2235 pkt
->u
.alter_resp
.ctx_list
[0].result
!= 0) {
2236 state
->p
->last_fault_code
= DCERPC_NCA_S_PROTO_ERROR
;
2237 tevent_req_nterror(req
, NT_STATUS_NET_WRITE_FAULT
);
2241 /* the alter_resp might contain a reply set of credentials */
2242 if (conn
->security_state
.auth_info
&&
2243 pkt
->u
.alter_resp
.auth_info
.length
) {
2244 uint32_t auth_length
;
2246 status
= dcerpc_pull_auth_trailer(pkt
, conn
, &pkt
->u
.alter_resp
.auth_info
,
2247 conn
->security_state
.auth_info
, &auth_length
, true);
2248 if (tevent_req_nterror(req
, status
)) {
2253 tevent_req_done(req
);
2256 NTSTATUS
dcerpc_alter_context_recv(struct tevent_req
*req
)
2258 return tevent_req_simple_recv_ntstatus(req
);
2262 send a dcerpc alter_context request
2264 _PUBLIC_ NTSTATUS
dcerpc_alter_context(struct dcerpc_pipe
*p
,
2265 TALLOC_CTX
*mem_ctx
,
2266 const struct ndr_syntax_id
*syntax
,
2267 const struct ndr_syntax_id
*transfer_syntax
)
2269 struct tevent_req
*subreq
;
2270 struct tevent_context
*ev
= p
->conn
->event_ctx
;
2273 /* TODO: create a new event context here */
2275 subreq
= dcerpc_alter_context_send(mem_ctx
, ev
,
2276 p
, syntax
, transfer_syntax
);
2277 if (subreq
== NULL
) {
2278 return NT_STATUS_NO_MEMORY
;
2281 ok
= tevent_req_poll(subreq
, ev
);
2284 status
= map_nt_error_from_unix_common(errno
);
2288 return dcerpc_alter_context_recv(subreq
);
2291 static void dcerpc_transport_dead(struct dcecli_connection
*c
, NTSTATUS status
)
2293 if (c
->transport
.stream
== NULL
) {
2297 tevent_queue_stop(c
->transport
.write_queue
);
2298 TALLOC_FREE(c
->transport
.read_subreq
);
2299 TALLOC_FREE(c
->transport
.stream
);
2301 if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL
, status
)) {
2302 status
= NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
2305 if (NT_STATUS_EQUAL(NT_STATUS_OK
, status
)) {
2306 status
= NT_STATUS_END_OF_FILE
;
2309 dcerpc_recv_data(c
, NULL
, status
);
2314 shutdown SMB pipe connection
2316 struct dcerpc_shutdown_pipe_state
{
2317 struct dcecli_connection
*c
;
2321 static void dcerpc_shutdown_pipe_done(struct tevent_req
*subreq
);
2323 static NTSTATUS
dcerpc_shutdown_pipe(struct dcecli_connection
*c
, NTSTATUS status
)
2325 struct dcerpc_shutdown_pipe_state
*state
;
2326 struct tevent_req
*subreq
;
2328 if (c
->transport
.stream
== NULL
) {
2329 return NT_STATUS_OK
;
2332 state
= talloc_zero(c
, struct dcerpc_shutdown_pipe_state
);
2333 if (state
== NULL
) {
2334 return NT_STATUS_NO_MEMORY
;
2337 state
->status
= status
;
2339 subreq
= tstream_disconnect_send(state
, c
->event_ctx
, c
->transport
.stream
);
2340 if (subreq
== NULL
) {
2341 return NT_STATUS_NO_MEMORY
;
2343 tevent_req_set_callback(subreq
, dcerpc_shutdown_pipe_done
, state
);
2348 static void dcerpc_shutdown_pipe_done(struct tevent_req
*subreq
)
2350 struct dcerpc_shutdown_pipe_state
*state
=
2351 tevent_req_callback_data(subreq
, struct dcerpc_shutdown_pipe_state
);
2352 struct dcecli_connection
*c
= state
->c
;
2353 NTSTATUS status
= state
->status
;
2357 * here we ignore the return values...
2359 tstream_disconnect_recv(subreq
, &error
);
2360 TALLOC_FREE(subreq
);
2364 dcerpc_transport_dead(c
, status
);
2369 struct dcerpc_send_read_state
{
2370 struct dcecli_connection
*p
;
2373 static int dcerpc_send_read_state_destructor(struct dcerpc_send_read_state
*state
)
2375 struct dcecli_connection
*p
= state
->p
;
2377 p
->transport
.read_subreq
= NULL
;
2382 static void dcerpc_send_read_done(struct tevent_req
*subreq
);
2384 static NTSTATUS
dcerpc_send_read(struct dcecli_connection
*p
)
2386 struct dcerpc_send_read_state
*state
;
2388 if (p
->transport
.read_subreq
!= NULL
) {
2389 p
->transport
.pending_reads
++;
2390 return NT_STATUS_OK
;
2393 state
= talloc_zero(p
, struct dcerpc_send_read_state
);
2394 if (state
== NULL
) {
2395 return NT_STATUS_NO_MEMORY
;
2399 talloc_set_destructor(state
, dcerpc_send_read_state_destructor
);
2401 p
->transport
.read_subreq
= dcerpc_read_ncacn_packet_send(state
,
2403 p
->transport
.stream
);
2404 if (p
->transport
.read_subreq
== NULL
) {
2405 return NT_STATUS_NO_MEMORY
;
2407 tevent_req_set_callback(p
->transport
.read_subreq
, dcerpc_send_read_done
, state
);
2409 return NT_STATUS_OK
;
2412 static void dcerpc_send_read_done(struct tevent_req
*subreq
)
2414 struct dcerpc_send_read_state
*state
=
2415 tevent_req_callback_data(subreq
,
2416 struct dcerpc_send_read_state
);
2417 struct dcecli_connection
*p
= state
->p
;
2419 struct ncacn_packet
*pkt
;
2422 status
= dcerpc_read_ncacn_packet_recv(subreq
, state
,
2424 TALLOC_FREE(subreq
);
2425 if (!NT_STATUS_IS_OK(status
)) {
2427 dcerpc_transport_dead(p
, status
);
2432 * here we steal into thet connection context,
2433 * but p->transport.recv_data() will steal or free it again
2435 talloc_steal(p
, blob
.data
);
2438 if (p
->transport
.pending_reads
> 0) {
2439 p
->transport
.pending_reads
--;
2441 status
= dcerpc_send_read(p
);
2442 if (!NT_STATUS_IS_OK(status
)) {
2443 dcerpc_transport_dead(p
, status
);
2448 dcerpc_recv_data(p
, &blob
, NT_STATUS_OK
);
2451 struct dcerpc_send_request_state
{
2452 struct dcecli_connection
*p
;
2457 static int dcerpc_send_request_state_destructor(struct dcerpc_send_request_state
*state
)
2459 struct dcecli_connection
*p
= state
->p
;
2461 p
->transport
.read_subreq
= NULL
;
2466 static void dcerpc_send_request_wait_done(struct tevent_req
*subreq
);
2467 static void dcerpc_send_request_done(struct tevent_req
*subreq
);
2469 static NTSTATUS
dcerpc_send_request(struct dcecli_connection
*p
, DATA_BLOB
*data
,
2472 struct dcerpc_send_request_state
*state
;
2473 struct tevent_req
*subreq
;
2474 bool use_trans
= trigger_read
;
2476 if (p
->transport
.stream
== NULL
) {
2477 return NT_STATUS_CONNECTION_DISCONNECTED
;
2480 state
= talloc_zero(p
, struct dcerpc_send_request_state
);
2481 if (state
== NULL
) {
2482 return NT_STATUS_NO_MEMORY
;
2486 state
->blob
= data_blob_talloc(state
, data
->data
, data
->length
);
2487 if (state
->blob
.data
== NULL
) {
2489 return NT_STATUS_NO_MEMORY
;
2491 state
->iov
.iov_base
= (void *)state
->blob
.data
;
2492 state
->iov
.iov_len
= state
->blob
.length
;
2494 if (p
->transport
.read_subreq
!= NULL
) {
2498 if (!tstream_is_smbXcli_np(p
->transport
.stream
)) {
2504 * we need to block reads until our write is
2505 * the next in the write queue.
2507 p
->transport
.read_subreq
= tevent_queue_wait_send(state
, p
->event_ctx
,
2508 p
->transport
.write_queue
);
2509 if (p
->transport
.read_subreq
== NULL
) {
2511 return NT_STATUS_NO_MEMORY
;
2513 tevent_req_set_callback(p
->transport
.read_subreq
,
2514 dcerpc_send_request_wait_done
,
2517 talloc_set_destructor(state
, dcerpc_send_request_state_destructor
);
2519 trigger_read
= false;
2522 subreq
= tstream_writev_queue_send(state
, p
->event_ctx
,
2523 p
->transport
.stream
,
2524 p
->transport
.write_queue
,
2526 if (subreq
== NULL
) {
2528 return NT_STATUS_NO_MEMORY
;
2530 tevent_req_set_callback(subreq
, dcerpc_send_request_done
, state
);
2533 dcerpc_send_read(p
);
2536 return NT_STATUS_OK
;
2539 static void dcerpc_send_request_wait_done(struct tevent_req
*subreq
)
2541 struct dcerpc_send_request_state
*state
=
2542 tevent_req_callback_data(subreq
,
2543 struct dcerpc_send_request_state
);
2544 struct dcecli_connection
*p
= state
->p
;
2548 p
->transport
.read_subreq
= NULL
;
2549 talloc_set_destructor(state
, NULL
);
2551 ok
= tevent_queue_wait_recv(subreq
);
2554 dcerpc_transport_dead(p
, NT_STATUS_NO_MEMORY
);
2558 if (tevent_queue_length(p
->transport
.write_queue
) <= 2) {
2559 status
= tstream_smbXcli_np_use_trans(p
->transport
.stream
);
2560 if (!NT_STATUS_IS_OK(status
)) {
2562 dcerpc_transport_dead(p
, status
);
2567 /* we free subreq after tstream_cli_np_use_trans */
2568 TALLOC_FREE(subreq
);
2570 dcerpc_send_read(p
);
2573 static void dcerpc_send_request_done(struct tevent_req
*subreq
)
2575 struct dcerpc_send_request_state
*state
=
2576 tevent_req_callback_data(subreq
,
2577 struct dcerpc_send_request_state
);
2581 ret
= tstream_writev_queue_recv(subreq
, &error
);
2582 TALLOC_FREE(subreq
);
2584 struct dcecli_connection
*p
= state
->p
;
2585 NTSTATUS status
= map_nt_error_from_unix_common(error
);
2588 dcerpc_transport_dead(p
, status
);