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.session_key = dcerpc_generic_session_key;
148 c->security_state.generic_state = NULL;
151 * Windows uses 5840 for ncacn_ip_tcp,
152 * so we also use it (for every transport)
153 * by default. But we give the transport
154 * the chance to overwrite it.
156 c->srv_max_xmit_frag = 5840;
157 c->srv_max_recv_frag = 5840;
160 c->io_trigger = tevent_create_immediate(c);
161 if (c->io_trigger == NULL) {
166 talloc_set_destructor(c, dcerpc_connection_destructor);
171 struct dcerpc_bh_state {
172 struct dcerpc_pipe *p;
175 static bool dcerpc_bh_is_connected(struct dcerpc_binding_handle *h)
177 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
178 struct dcerpc_bh_state);
188 if (hs->p->conn->dead) {
195 static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle *h,
198 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
199 struct dcerpc_bh_state);
203 return DCERPC_REQUEST_TIMEOUT;
206 old = hs->p->request_timeout;
207 hs->p->request_timeout = timeout;
212 static void dcerpc_bh_auth_info(struct dcerpc_binding_handle *h,
213 enum dcerpc_AuthType *auth_type,
214 enum dcerpc_AuthLevel *auth_level)
216 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
217 struct dcerpc_bh_state);
223 if (hs->p->conn == NULL) {
227 *auth_type = hs->p->conn->security_state.auth_type;
228 *auth_level = hs->p->conn->security_state.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 status = dcerpc_verify_ncacn_packet_header(pkt, DCERPC_PKT_RESPONSE,
745 pkt->u.response.stub_and_verifier.length,
746 0, /* required_flags */
747 DCERPC_PFC_FLAG_FIRST |
748 DCERPC_PFC_FLAG_LAST);
749 if (!NT_STATUS_IS_OK(status)) {
753 switch (c->security_state.auth_level) {
754 case DCERPC_AUTH_LEVEL_PRIVACY:
755 case DCERPC_AUTH_LEVEL_INTEGRITY:
758 case DCERPC_AUTH_LEVEL_CONNECT:
759 if (pkt->auth_length != 0) {
763 case DCERPC_AUTH_LEVEL_NONE:
764 if (pkt->auth_length != 0) {
765 return NT_STATUS_INVALID_NETWORK_RESPONSE;
770 return NT_STATUS_INVALID_LEVEL;
773 if (pkt->auth_length == 0) {
774 return NT_STATUS_INVALID_NETWORK_RESPONSE;
777 if (c->security_state.generic_state == NULL) {
778 return NT_STATUS_INTERNAL_ERROR;
781 status = dcerpc_pull_auth_trailer(pkt, mem_ctx,
782 &pkt->u.response.stub_and_verifier,
783 &auth, &auth_length, false);
784 NT_STATUS_NOT_OK_RETURN(status);
786 pkt->u.response.stub_and_verifier.length -= auth_length;
788 if (auth.auth_type != c->security_state.auth_type) {
789 return NT_STATUS_RPC_PROTOCOL_ERROR;
792 if (auth.auth_level != c->security_state.auth_level) {
793 return NT_STATUS_RPC_PROTOCOL_ERROR;
796 if (auth.auth_context_id != c->security_state.auth_context_id) {
797 return NT_STATUS_RPC_PROTOCOL_ERROR;
800 /* check signature or unseal the packet */
801 switch (c->security_state.auth_level) {
802 case DCERPC_AUTH_LEVEL_PRIVACY:
803 status = gensec_unseal_packet(c->security_state.generic_state,
804 raw_packet->data + DCERPC_REQUEST_LENGTH,
805 pkt->u.response.stub_and_verifier.length,
807 raw_packet->length - auth.credentials.length,
809 memcpy(pkt->u.response.stub_and_verifier.data,
810 raw_packet->data + DCERPC_REQUEST_LENGTH,
811 pkt->u.response.stub_and_verifier.length);
814 case DCERPC_AUTH_LEVEL_INTEGRITY:
815 status = gensec_check_packet(c->security_state.generic_state,
816 pkt->u.response.stub_and_verifier.data,
817 pkt->u.response.stub_and_verifier.length,
819 raw_packet->length - auth.credentials.length,
823 case DCERPC_AUTH_LEVEL_CONNECT:
824 /* for now we ignore possible signatures here */
825 status = NT_STATUS_OK;
829 status = NT_STATUS_INVALID_LEVEL;
833 /* remove the indicated amount of padding */
834 if (pkt->u.response.stub_and_verifier.length < auth.auth_pad_length) {
835 return NT_STATUS_INFO_LENGTH_MISMATCH;
837 pkt->u.response.stub_and_verifier.length -= auth.auth_pad_length;
844 push a dcerpc request packet into a blob, possibly signing it.
846 static NTSTATUS ncacn_push_request_sign(struct dcecli_connection *c,
847 DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
849 struct ncacn_packet *pkt)
852 struct ndr_push *ndr;
854 size_t payload_length;
855 enum ndr_err_code ndr_err;
856 size_t hdr_size = DCERPC_REQUEST_LENGTH;
857 struct dcerpc_auth auth_info = {
858 .auth_type = c->security_state.auth_type,
859 .auth_level = c->security_state.auth_level,
860 .auth_context_id = c->security_state.auth_context_id,
863 switch (c->security_state.auth_level) {
864 case DCERPC_AUTH_LEVEL_PRIVACY:
865 case DCERPC_AUTH_LEVEL_INTEGRITY:
867 return NT_STATUS_INTERNAL_ERROR;
871 case DCERPC_AUTH_LEVEL_CONNECT:
872 /* TODO: let the gensec mech decide if it wants to generate a signature */
873 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
875 case DCERPC_AUTH_LEVEL_NONE:
876 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
879 return NT_STATUS_INVALID_LEVEL;
882 ndr = ndr_push_init_ctx(mem_ctx);
884 return NT_STATUS_NO_MEMORY;
887 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
888 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
891 if (c->flags & DCERPC_NDR64) {
892 ndr->flags |= LIBNDR_FLAG_NDR64;
895 if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
896 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
900 ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
901 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
902 return ndr_map_error2ntstatus(ndr_err);
905 /* pad to 16 byte multiple in the payload portion of the
906 packet. This matches what w2k3 does. Note that we can't use
907 ndr_push_align() as that is relative to the start of the
908 whole packet, whereas w2k8 wants it relative to the start
910 auth_info.auth_pad_length =
911 DCERPC_AUTH_PAD_LENGTH(pkt->u.request.stub_and_verifier.length);
912 ndr_err = ndr_push_zero(ndr, auth_info.auth_pad_length);
913 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
914 return ndr_map_error2ntstatus(ndr_err);
917 payload_length = pkt->u.request.stub_and_verifier.length +
918 auth_info.auth_pad_length;
920 /* add the auth verifier */
921 ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, &auth_info);
922 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
923 return ndr_map_error2ntstatus(ndr_err);
926 /* extract the whole packet as a blob */
927 *blob = ndr_push_blob(ndr);
930 * Setup the frag and auth length in the packet buffer.
931 * This is needed if the GENSEC mech does AEAD signing
932 * of the packet headers. The signature itself will be
935 dcerpc_set_frag_length(blob, blob->length + sig_size);
936 dcerpc_set_auth_length(blob, sig_size);
938 /* sign or seal the packet */
939 switch (c->security_state.auth_level) {
940 case DCERPC_AUTH_LEVEL_PRIVACY:
941 status = gensec_seal_packet(c->security_state.generic_state,
943 blob->data + hdr_size,
948 if (!NT_STATUS_IS_OK(status)) {
953 case DCERPC_AUTH_LEVEL_INTEGRITY:
954 status = gensec_sign_packet(c->security_state.generic_state,
956 blob->data + hdr_size,
961 if (!NT_STATUS_IS_OK(status)) {
967 status = NT_STATUS_INVALID_LEVEL;
971 if (creds2.length != sig_size) {
972 /* this means the sig_size estimate for the signature
973 was incorrect. We have to correct the packet
974 sizes. That means we could go over the max fragment
976 DEBUG(3,("ncacn_push_request_sign: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n",
977 (unsigned) creds2.length,
979 (unsigned) auth_info.auth_pad_length,
980 (unsigned) pkt->u.request.stub_and_verifier.length));
981 dcerpc_set_frag_length(blob, blob->length + creds2.length);
982 dcerpc_set_auth_length(blob, creds2.length);
985 if (!data_blob_append(mem_ctx, blob, creds2.data, creds2.length)) {
986 return NT_STATUS_NO_MEMORY;
994 fill in the fixed values in a dcerpc header
996 static void init_ncacn_hdr(struct dcecli_connection *c, struct ncacn_packet *pkt)
999 pkt->rpc_vers_minor = 0;
1000 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
1003 pkt->drep[0] = DCERPC_DREP_LE;
1011 map a bind nak reason to a NTSTATUS
1013 static NTSTATUS dcerpc_map_nak_reason(enum dcerpc_bind_nak_reason reason)
1016 case DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED:
1017 return NT_STATUS_REVISION_MISMATCH;
1018 case DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE:
1019 return NT_STATUS_INVALID_PARAMETER;
1023 return NT_STATUS_UNSUCCESSFUL;
1026 static NTSTATUS dcerpc_map_ack_reason(const struct dcerpc_ack_ctx *ack)
1029 return NT_STATUS_RPC_PROTOCOL_ERROR;
1032 switch (ack->result) {
1033 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
1035 * We have not asked for this...
1037 return NT_STATUS_RPC_PROTOCOL_ERROR;
1042 switch (ack->reason.value) {
1043 case DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED:
1044 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
1045 case DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED:
1046 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
1050 return NT_STATUS_UNSUCCESSFUL;
1054 remove requests from the pending or queued queues
1056 static int dcerpc_req_dequeue(struct rpc_request *req)
1058 switch (req->state) {
1059 case RPC_REQUEST_QUEUED:
1060 DLIST_REMOVE(req->p->conn->request_queue, req);
1062 case RPC_REQUEST_PENDING:
1063 DLIST_REMOVE(req->p->conn->pending, req);
1065 case RPC_REQUEST_DONE:
1073 mark the dcerpc connection dead. All outstanding requests get an error
1075 static void dcerpc_connection_dead(struct dcecli_connection *conn, NTSTATUS status)
1077 if (conn->dead) return;
1081 TALLOC_FREE(conn->io_trigger);
1082 conn->io_trigger_pending = false;
1084 dcerpc_shutdown_pipe(conn, status);
1086 /* all pending requests get the error */
1087 while (conn->pending) {
1088 struct rpc_request *req = conn->pending;
1089 dcerpc_req_dequeue(req);
1090 req->state = RPC_REQUEST_DONE;
1091 req->status = status;
1092 if (req->async.callback) {
1093 req->async.callback(req);
1097 /* all requests, which are not shipped */
1098 while (conn->request_queue) {
1099 struct rpc_request *req = conn->request_queue;
1100 dcerpc_req_dequeue(req);
1101 req->state = RPC_REQUEST_DONE;
1102 req->status = status;
1103 if (req->async.callback) {
1104 req->async.callback(req);
1108 talloc_set_destructor(conn, NULL);
1109 if (conn->free_skipped) {
1115 forward declarations of the recv_data handlers for the types of
1116 packets we need to handle
1118 static void dcerpc_request_recv_data(struct dcecli_connection *c,
1119 DATA_BLOB *raw_packet, struct ncacn_packet *pkt);
1122 receive a dcerpc reply from the transport. Here we work out what
1123 type of reply it is (normal request, bind or alter context) and
1124 dispatch to the appropriate handler
1126 static void dcerpc_recv_data(struct dcecli_connection *conn, DATA_BLOB *blob, NTSTATUS status)
1128 struct ncacn_packet pkt;
1134 if (NT_STATUS_IS_OK(status) && blob->length == 0) {
1135 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1138 /* the transport may be telling us of a severe error, such as
1140 if (!NT_STATUS_IS_OK(status)) {
1141 data_blob_free(blob);
1142 dcerpc_connection_dead(conn, status);
1146 /* parse the basic packet to work out what type of response this is */
1147 status = ncacn_pull(conn, blob, blob->data, &pkt);
1148 if (!NT_STATUS_IS_OK(status)) {
1149 data_blob_free(blob);
1150 dcerpc_connection_dead(conn, status);
1154 dcerpc_request_recv_data(conn, blob, &pkt);
1158 handle timeouts of individual dcerpc requests
1160 static void dcerpc_timeout_handler(struct tevent_context *ev, struct tevent_timer *te,
1161 struct timeval t, void *private_data)
1163 struct rpc_request *req = talloc_get_type(private_data, struct rpc_request);
1165 if (req->ignore_timeout) {
1166 dcerpc_req_dequeue(req);
1167 req->state = RPC_REQUEST_DONE;
1168 req->status = NT_STATUS_IO_TIMEOUT;
1169 if (req->async.callback) {
1170 req->async.callback(req);
1175 dcerpc_connection_dead(req->p->conn, NT_STATUS_IO_TIMEOUT);
1178 struct dcerpc_bind_state {
1179 struct tevent_context *ev;
1180 struct dcerpc_pipe *p;
1183 static void dcerpc_bind_fail_handler(struct rpc_request *subreq);
1184 static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
1185 DATA_BLOB *raw_packet,
1186 struct ncacn_packet *pkt);
1188 struct tevent_req *dcerpc_bind_send(TALLOC_CTX *mem_ctx,
1189 struct tevent_context *ev,
1190 struct dcerpc_pipe *p,
1191 const struct ndr_syntax_id *syntax,
1192 const struct ndr_syntax_id *transfer_syntax)
1194 struct tevent_req *req;
1195 struct dcerpc_bind_state *state;
1196 struct ncacn_packet pkt;
1199 struct rpc_request *subreq;
1202 req = tevent_req_create(mem_ctx, &state,
1203 struct dcerpc_bind_state);
1211 p->syntax = *syntax;
1212 p->transfer_syntax = *transfer_syntax;
1214 flags = dcerpc_binding_get_flags(p->binding);
1216 init_ncacn_hdr(p->conn, &pkt);
1218 pkt.ptype = DCERPC_PKT_BIND;
1219 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1220 pkt.call_id = p->conn->call_id;
1221 pkt.auth_length = 0;
1223 if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
1224 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1227 if (p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) {
1228 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1231 pkt.u.bind.max_xmit_frag = p->conn->srv_max_xmit_frag;
1232 pkt.u.bind.max_recv_frag = p->conn->srv_max_recv_frag;
1233 pkt.u.bind.assoc_group_id = dcerpc_binding_get_assoc_group_id(p->binding);
1234 pkt.u.bind.num_contexts = 1;
1235 pkt.u.bind.ctx_list = talloc_array(mem_ctx, struct dcerpc_ctx_list, 1);
1236 if (tevent_req_nomem(pkt.u.bind.ctx_list, req)) {
1237 return tevent_req_post(req, ev);
1239 pkt.u.bind.ctx_list[0].context_id = p->context_id;
1240 pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1;
1241 pkt.u.bind.ctx_list[0].abstract_syntax = p->syntax;
1242 pkt.u.bind.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
1243 pkt.u.bind.auth_info = data_blob(NULL, 0);
1245 /* construct the NDR form of the packet */
1246 status = ncacn_push_auth(&blob, state, &pkt,
1247 p->conn->security_state.tmp_auth_info.out);
1248 if (tevent_req_nterror(req, status)) {
1249 return tevent_req_post(req, ev);
1253 * we allocate a dcerpc_request so we can be in the same
1254 * request queue as normal requests
1256 subreq = talloc_zero(state, struct rpc_request);
1257 if (tevent_req_nomem(subreq, req)) {
1258 return tevent_req_post(req, ev);
1261 subreq->state = RPC_REQUEST_PENDING;
1262 subreq->call_id = pkt.call_id;
1263 subreq->async.private_data = req;
1264 subreq->async.callback = dcerpc_bind_fail_handler;
1266 subreq->recv_handler = dcerpc_bind_recv_handler;
1267 DLIST_ADD_END(p->conn->pending, subreq, struct rpc_request *);
1268 talloc_set_destructor(subreq, dcerpc_req_dequeue);
1270 status = dcerpc_send_request(p->conn, &blob, true);
1271 if (tevent_req_nterror(req, status)) {
1272 return tevent_req_post(req, ev);
1275 tevent_add_timer(ev, subreq,
1276 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
1277 dcerpc_timeout_handler, subreq);
1282 static void dcerpc_bind_fail_handler(struct rpc_request *subreq)
1284 struct tevent_req *req =
1285 talloc_get_type_abort(subreq->async.private_data,
1287 struct dcerpc_bind_state *state =
1288 tevent_req_data(req,
1289 struct dcerpc_bind_state);
1290 NTSTATUS status = subreq->status;
1292 TALLOC_FREE(subreq);
1295 * We trigger the callback in the next event run
1296 * because the code in this file might trigger
1297 * multiple request callbacks from within a single
1300 * In order to avoid segfaults from within
1301 * dcerpc_connection_dead() we call
1302 * tevent_req_defer_callback().
1304 tevent_req_defer_callback(req, state->ev);
1306 tevent_req_nterror(req, status);
1309 static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
1310 DATA_BLOB *raw_packet,
1311 struct ncacn_packet *pkt)
1313 struct tevent_req *req =
1314 talloc_get_type_abort(subreq->async.private_data,
1316 struct dcerpc_bind_state *state =
1317 tevent_req_data(req,
1318 struct dcerpc_bind_state);
1319 struct dcecli_connection *conn = state->p->conn;
1320 struct dcecli_security *sec = &conn->security_state;
1321 struct dcerpc_binding *b = NULL;
1326 * Note that pkt is allocated under raw_packet->data,
1327 * while raw_packet->data is a child of subreq.
1329 talloc_steal(state, raw_packet->data);
1330 TALLOC_FREE(subreq);
1333 * We trigger the callback in the next event run
1334 * because the code in this file might trigger
1335 * multiple request callbacks from within a single
1338 * In order to avoid segfaults from within
1339 * dcerpc_connection_dead() we call
1340 * tevent_req_defer_callback().
1342 tevent_req_defer_callback(req, state->ev);
1344 if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
1345 status = dcerpc_map_nak_reason(pkt->u.bind_nak.reject_reason);
1347 DEBUG(2,("dcerpc: bind_nak reason %d - %s\n",
1348 pkt->u.bind_nak.reject_reason, nt_errstr(status)));
1350 tevent_req_nterror(req, status);
1354 status = dcerpc_verify_ncacn_packet_header(pkt,
1355 DCERPC_PKT_BIND_ACK,
1356 pkt->u.bind_ack.auth_info.length,
1357 DCERPC_PFC_FLAG_FIRST |
1358 DCERPC_PFC_FLAG_LAST,
1359 DCERPC_PFC_FLAG_CONC_MPX |
1360 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
1361 if (!NT_STATUS_IS_OK(status)) {
1362 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1363 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1367 if (pkt->u.bind_ack.num_results != 1) {
1368 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1369 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1373 if (pkt->u.bind_ack.ctx_list[0].result != 0) {
1374 status = dcerpc_map_ack_reason(&pkt->u.bind_ack.ctx_list[0]);
1375 DEBUG(2,("dcerpc: bind_ack failed - reason %d - %s\n",
1376 pkt->u.bind_ack.ctx_list[0].reason.value,
1377 nt_errstr(status)));
1378 tevent_req_nterror(req, status);
1383 * DCE-RPC 1.1 (c706) specifies
1384 * CONST_MUST_RCV_FRAG_SIZE as 1432
1386 if (pkt->u.bind_ack.max_xmit_frag < 1432) {
1387 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1388 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1391 if (pkt->u.bind_ack.max_recv_frag < 1432) {
1392 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1393 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1396 conn->srv_max_xmit_frag = MIN(conn->srv_max_xmit_frag,
1397 pkt->u.bind_ack.max_xmit_frag);
1398 conn->srv_max_recv_frag = MIN(conn->srv_max_recv_frag,
1399 pkt->u.bind_ack.max_recv_frag);
1401 flags = dcerpc_binding_get_flags(state->p->binding);
1403 if ((flags & DCERPC_CONCURRENT_MULTIPLEX) &&
1404 (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX)) {
1405 conn->flags |= DCERPC_CONCURRENT_MULTIPLEX;
1408 if ((conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) &&
1409 (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
1410 conn->flags |= DCERPC_HEADER_SIGNING;
1413 /* the bind_ack might contain a reply set of credentials */
1414 if (pkt->auth_length != 0 && sec->tmp_auth_info.in != NULL) {
1415 uint32_t auth_length;
1417 status = dcerpc_pull_auth_trailer(pkt, sec->tmp_auth_info.mem,
1418 &pkt->u.bind_ack.auth_info,
1419 sec->tmp_auth_info.in,
1420 &auth_length, true);
1421 if (tevent_req_nterror(req, status)) {
1427 * We're the owner of the binding, so we're allowed to modify it.
1429 b = discard_const_p(struct dcerpc_binding, state->p->binding);
1430 status = dcerpc_binding_set_assoc_group_id(b,
1431 pkt->u.bind_ack.assoc_group_id);
1432 if (tevent_req_nterror(req, status)) {
1436 tevent_req_done(req);
1439 NTSTATUS dcerpc_bind_recv(struct tevent_req *req)
1441 return tevent_req_simple_recv_ntstatus(req);
1445 perform a continued bind (and auth3)
1447 NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p,
1448 TALLOC_CTX *mem_ctx)
1450 struct ncacn_packet pkt;
1455 flags = dcerpc_binding_get_flags(p->binding);
1457 init_ncacn_hdr(p->conn, &pkt);
1459 pkt.ptype = DCERPC_PKT_AUTH3;
1460 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1461 pkt.call_id = next_call_id(p->conn);
1462 pkt.auth_length = 0;
1463 pkt.u.auth3.auth_info = data_blob(NULL, 0);
1465 if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
1466 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1469 /* construct the NDR form of the packet */
1470 status = ncacn_push_auth(&blob, mem_ctx, &pkt,
1471 p->conn->security_state.tmp_auth_info.out);
1472 if (!NT_STATUS_IS_OK(status)) {
1476 /* send it on its way */
1477 status = dcerpc_send_request(p->conn, &blob, false);
1478 if (!NT_STATUS_IS_OK(status)) {
1482 return NT_STATUS_OK;
1487 process a fragment received from the transport layer during a
1490 This function frees the data
1492 static void dcerpc_request_recv_data(struct dcecli_connection *c,
1493 DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
1495 struct rpc_request *req;
1496 unsigned int length;
1497 NTSTATUS status = NT_STATUS_OK;
1500 if this is an authenticated connection then parse and check
1501 the auth info. We have to do this before finding the
1502 matching packet, as the request structure might have been
1503 removed due to a timeout, but if it has been we still need
1504 to run the auth routines so that we don't get the sign/seal
1505 info out of step with the server
1507 if (pkt->ptype == DCERPC_PKT_RESPONSE) {
1508 status = ncacn_pull_request_auth(c, raw_packet->data, raw_packet, pkt);
1511 /* find the matching request */
1512 for (req=c->pending;req;req=req->next) {
1513 if (pkt->call_id == req->call_id) break;
1517 /* useful for testing certain vendors RPC servers */
1518 if (req == NULL && c->pending && pkt->call_id == 0) {
1519 DEBUG(0,("HACK FOR INCORRECT CALL ID\n"));
1525 DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt->call_id));
1526 data_blob_free(raw_packet);
1530 talloc_steal(req, raw_packet->data);
1532 if (req->recv_handler != NULL) {
1533 dcerpc_req_dequeue(req);
1534 req->state = RPC_REQUEST_DONE;
1537 * We have to look at shipping further requests before calling
1538 * the async function, that one might close the pipe
1540 dcerpc_schedule_io_trigger(c);
1542 req->recv_handler(req, raw_packet, pkt);
1546 if (pkt->ptype == DCERPC_PKT_FAULT) {
1547 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
1548 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
1549 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1550 dcerpc_connection_dead(c, status);
1553 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1554 dcerpc_connection_dead(c, status);
1557 req->fault_code = pkt->u.fault.status;
1558 req->status = NT_STATUS_NET_WRITE_FAULT;
1562 if (pkt->ptype != DCERPC_PKT_RESPONSE) {
1563 DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
1565 dcerpc_connection_dead(c, NT_STATUS_RPC_PROTOCOL_ERROR);
1569 /* now check the status from the auth routines, and if it failed then fail
1570 this request accordingly */
1571 if (!NT_STATUS_IS_OK(status)) {
1572 dcerpc_connection_dead(c, status);
1576 length = pkt->u.response.stub_and_verifier.length;
1578 if (req->payload.length + length > DCERPC_NCACN_PAYLOAD_MAX_SIZE) {
1579 DEBUG(2,("Unexpected total payload 0x%X > 0x%X dcerpc response\n",
1580 (unsigned)req->payload.length + length,
1581 DCERPC_NCACN_PAYLOAD_MAX_SIZE));
1582 dcerpc_connection_dead(c, NT_STATUS_RPC_PROTOCOL_ERROR);
1587 req->payload.data = talloc_realloc(req,
1590 req->payload.length + length);
1591 if (!req->payload.data) {
1592 req->status = NT_STATUS_NO_MEMORY;
1595 memcpy(req->payload.data+req->payload.length,
1596 pkt->u.response.stub_and_verifier.data, length);
1597 req->payload.length += length;
1600 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1601 data_blob_free(raw_packet);
1602 dcerpc_send_read(c);
1606 if (req->verify_bitmask1) {
1607 req->p->conn->security_state.verified_bitmask1 = true;
1609 if (req->verify_pcontext) {
1610 req->p->verified_pcontext = true;
1613 if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
1614 req->flags |= DCERPC_PULL_BIGENDIAN;
1616 req->flags &= ~DCERPC_PULL_BIGENDIAN;
1620 data_blob_free(raw_packet);
1622 /* we've got the full payload */
1623 dcerpc_req_dequeue(req);
1624 req->state = RPC_REQUEST_DONE;
1627 * We have to look at shipping further requests before calling
1628 * the async function, that one might close the pipe
1630 dcerpc_schedule_io_trigger(c);
1632 if (req->async.callback) {
1633 req->async.callback(req);
1637 static NTSTATUS dcerpc_request_prepare_vt(struct rpc_request *req);
1640 perform the send side of a async dcerpc request
1642 static struct rpc_request *dcerpc_request_send(TALLOC_CTX *mem_ctx,
1643 struct dcerpc_pipe *p,
1644 const struct GUID *object,
1646 DATA_BLOB *stub_data)
1648 struct rpc_request *req;
1651 req = talloc_zero(mem_ctx, struct rpc_request);
1657 req->call_id = next_call_id(p->conn);
1658 req->state = RPC_REQUEST_QUEUED;
1660 if (object != NULL) {
1661 req->object = (struct GUID *)talloc_memdup(req, (const void *)object, sizeof(*object));
1662 if (req->object == NULL) {
1669 req->request_data.length = stub_data->length;
1670 req->request_data.data = stub_data->data;
1672 status = dcerpc_request_prepare_vt(req);
1673 if (!NT_STATUS_IS_OK(status)) {
1678 DLIST_ADD_END(p->conn->request_queue, req, struct rpc_request *);
1679 talloc_set_destructor(req, dcerpc_req_dequeue);
1681 dcerpc_schedule_io_trigger(p->conn);
1683 if (p->request_timeout) {
1684 tevent_add_timer(p->conn->event_ctx, req,
1685 timeval_current_ofs(p->request_timeout, 0),
1686 dcerpc_timeout_handler, req);
1692 static NTSTATUS dcerpc_request_prepare_vt(struct rpc_request *req)
1694 struct dcecli_security *sec = &req->p->conn->security_state;
1695 struct dcerpc_sec_verification_trailer *t;
1696 struct dcerpc_sec_vt *c = NULL;
1697 struct ndr_push *ndr = NULL;
1698 enum ndr_err_code ndr_err;
1700 if (sec->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1701 return NT_STATUS_OK;
1704 t = talloc_zero(req, struct dcerpc_sec_verification_trailer);
1706 return NT_STATUS_NO_MEMORY;
1709 if (!sec->verified_bitmask1) {
1710 t->commands = talloc_realloc(t, t->commands,
1711 struct dcerpc_sec_vt,
1712 t->count.count + 1);
1713 if (t->commands == NULL) {
1714 return NT_STATUS_NO_MEMORY;
1716 c = &t->commands[t->count.count++];
1719 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1720 if (req->p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) {
1721 c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1723 req->verify_bitmask1 = true;
1726 if (!req->p->verified_pcontext) {
1727 t->commands = talloc_realloc(t, t->commands,
1728 struct dcerpc_sec_vt,
1729 t->count.count + 1);
1730 if (t->commands == NULL) {
1731 return NT_STATUS_NO_MEMORY;
1733 c = &t->commands[t->count.count++];
1736 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1737 c->u.pcontext.abstract_syntax = req->p->syntax;
1738 c->u.pcontext.transfer_syntax = req->p->transfer_syntax;
1740 req->verify_pcontext = true;
1743 if (!(req->p->conn->flags & DCERPC_HEADER_SIGNING)) {
1744 t->commands = talloc_realloc(t, t->commands,
1745 struct dcerpc_sec_vt,
1746 t->count.count + 1);
1747 if (t->commands == NULL) {
1748 return NT_STATUS_NO_MEMORY;
1750 c = &t->commands[t->count.count++];
1753 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1754 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1755 if (req->p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
1756 c->u.header2.drep[0] = 0;
1758 c->u.header2.drep[0] = DCERPC_DREP_LE;
1760 c->u.header2.drep[1] = 0;
1761 c->u.header2.drep[2] = 0;
1762 c->u.header2.drep[3] = 0;
1763 c->u.header2.call_id = req->call_id;
1764 c->u.header2.context_id = req->p->context_id;
1765 c->u.header2.opnum = req->opnum;
1768 if (t->count.count == 0) {
1770 return NT_STATUS_OK;
1773 c = &t->commands[t->count.count - 1];
1774 c->command |= DCERPC_SEC_VT_COMMAND_END;
1776 if (DEBUGLEVEL >= 10) {
1777 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1780 ndr = ndr_push_init_ctx(req);
1782 return NT_STATUS_NO_MEMORY;
1786 * for now we just copy and append
1789 ndr_err = ndr_push_bytes(ndr, req->request_data.data,
1790 req->request_data.length);
1791 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1792 return ndr_map_error2ntstatus(ndr_err);
1795 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1796 NDR_SCALARS | NDR_BUFFERS,
1798 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1799 return ndr_map_error2ntstatus(ndr_err);
1801 req->request_data = ndr_push_blob(ndr);
1803 return NT_STATUS_OK;
1807 Send a request using the transport
1810 static void dcerpc_ship_next_request(struct dcecli_connection *c)
1812 struct rpc_request *req;
1813 struct dcerpc_pipe *p;
1814 DATA_BLOB *stub_data;
1815 struct ncacn_packet pkt;
1817 uint32_t remaining, chunk_size;
1818 bool first_packet = true;
1819 size_t sig_size = 0;
1820 bool need_async = false;
1821 bool can_async = true;
1823 req = c->request_queue;
1829 stub_data = &req->request_data;
1835 if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1836 can_async = gensec_have_feature(c->security_state.generic_state,
1837 GENSEC_FEATURE_ASYNC_REPLIES);
1840 if (need_async && !can_async) {
1841 req->wait_for_sync = true;
1845 DLIST_REMOVE(c->request_queue, req);
1846 DLIST_ADD(c->pending, req);
1847 req->state = RPC_REQUEST_PENDING;
1849 init_ncacn_hdr(p->conn, &pkt);
1851 remaining = stub_data->length;
1853 /* we can write a full max_recv_frag size, minus the dcerpc
1854 request header size */
1855 chunk_size = p->conn->srv_max_recv_frag;
1856 chunk_size -= DCERPC_REQUEST_LENGTH;
1857 if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1858 size_t max_payload = chunk_size;
1860 max_payload -= DCERPC_AUTH_TRAILER_LENGTH;
1861 max_payload -= (max_payload % DCERPC_AUTH_PAD_ALIGNMENT);
1863 sig_size = gensec_sig_size(c->security_state.generic_state,
1866 chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
1867 chunk_size -= sig_size;
1870 chunk_size -= (chunk_size % DCERPC_AUTH_PAD_ALIGNMENT);
1872 pkt.ptype = DCERPC_PKT_REQUEST;
1873 pkt.call_id = req->call_id;
1874 pkt.auth_length = 0;
1876 pkt.u.request.context_id = p->context_id;
1877 pkt.u.request.opnum = req->opnum;
1880 pkt.u.request.object.object = *req->object;
1881 pkt.pfc_flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1882 chunk_size -= ndr_size_GUID(req->object,0);
1885 /* we send a series of pdus without waiting for a reply */
1886 while (remaining > 0 || first_packet) {
1887 uint32_t chunk = MIN(chunk_size, remaining);
1888 bool last_frag = false;
1889 bool do_trans = false;
1891 first_packet = false;
1892 pkt.pfc_flags &= ~(DCERPC_PFC_FLAG_FIRST |DCERPC_PFC_FLAG_LAST);
1894 if (remaining == stub_data->length) {
1895 pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST;
1897 if (chunk == remaining) {
1898 pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
1902 pkt.u.request.alloc_hint = remaining;
1903 pkt.u.request.stub_and_verifier.data = stub_data->data +
1904 (stub_data->length - remaining);
1905 pkt.u.request.stub_and_verifier.length = chunk;
1907 req->status = ncacn_push_request_sign(p->conn, &blob, req, sig_size, &pkt);
1908 if (!NT_STATUS_IS_OK(req->status)) {
1909 req->state = RPC_REQUEST_DONE;
1910 DLIST_REMOVE(p->conn->pending, req);
1914 if (last_frag && !need_async) {
1918 req->status = dcerpc_send_request(p->conn, &blob, do_trans);
1919 if (!NT_STATUS_IS_OK(req->status)) {
1920 req->state = RPC_REQUEST_DONE;
1921 DLIST_REMOVE(p->conn->pending, req);
1925 if (last_frag && !do_trans) {
1926 req->status = dcerpc_send_read(p->conn);
1927 if (!NT_STATUS_IS_OK(req->status)) {
1928 req->state = RPC_REQUEST_DONE;
1929 DLIST_REMOVE(p->conn->pending, req);
1938 static void dcerpc_io_trigger(struct tevent_context *ctx,
1939 struct tevent_immediate *im,
1942 struct dcecli_connection *c =
1943 talloc_get_type_abort(private_data,
1944 struct dcecli_connection);
1946 c->io_trigger_pending = false;
1948 dcerpc_schedule_io_trigger(c);
1950 dcerpc_ship_next_request(c);
1953 static void dcerpc_schedule_io_trigger(struct dcecli_connection *c)
1959 if (c->request_queue == NULL) {
1963 if (c->request_queue->wait_for_sync && c->pending) {
1967 if (c->io_trigger_pending) {
1971 c->io_trigger_pending = true;
1973 tevent_schedule_immediate(c->io_trigger,
1980 perform the receive side of a async dcerpc request
1982 static NTSTATUS dcerpc_request_recv(struct rpc_request *req,
1983 TALLOC_CTX *mem_ctx,
1984 DATA_BLOB *stub_data)
1988 while (req->state != RPC_REQUEST_DONE) {
1989 struct tevent_context *ctx = req->p->conn->event_ctx;
1990 if (tevent_loop_once(ctx) != 0) {
1991 return NT_STATUS_CONNECTION_DISCONNECTED;
1994 *stub_data = req->payload;
1995 status = req->status;
1996 if (stub_data->data) {
1997 stub_data->data = talloc_steal(mem_ctx, stub_data->data);
1999 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
2000 req->p->last_fault_code = req->fault_code;
2002 talloc_unlink(talloc_parent(req), req);
2007 this is a paranoid NDR validator. For every packet we push onto the wire
2008 we pull it back again, then push it again. Then we compare the raw NDR data
2009 for that to the NDR we initially generated. If they don't match then we know
2010 we must have a bug in either the pull or push side of our code
2012 static NTSTATUS dcerpc_ndr_validate_in(struct dcecli_connection *c,
2013 TALLOC_CTX *mem_ctx,
2016 ndr_push_flags_fn_t ndr_push,
2017 ndr_pull_flags_fn_t ndr_pull)
2020 struct ndr_pull *pull;
2021 struct ndr_push *push;
2023 enum ndr_err_code ndr_err;
2025 st = talloc_size(mem_ctx, struct_size);
2027 return NT_STATUS_NO_MEMORY;
2030 pull = ndr_pull_init_flags(c, &blob, mem_ctx);
2032 return NT_STATUS_NO_MEMORY;
2034 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
2036 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
2037 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
2040 if (c->flags & DCERPC_NDR64) {
2041 pull->flags |= LIBNDR_FLAG_NDR64;
2044 ndr_err = ndr_pull(pull, NDR_IN, st);
2045 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2046 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2047 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
2048 "failed input validation pull - %s",
2050 return ndr_map_error2ntstatus(ndr_err);
2053 push = ndr_push_init_ctx(mem_ctx);
2055 return NT_STATUS_NO_MEMORY;
2058 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
2059 push->flags |= LIBNDR_FLAG_BIGENDIAN;
2062 if (c->flags & DCERPC_NDR64) {
2063 push->flags |= LIBNDR_FLAG_NDR64;
2066 ndr_err = ndr_push(push, NDR_IN, st);
2067 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2068 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2069 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
2070 "failed input validation push - %s",
2072 return ndr_map_error2ntstatus(ndr_err);
2075 blob2 = ndr_push_blob(push);
2077 if (data_blob_cmp(&blob, &blob2) != 0) {
2078 DEBUG(3,("original:\n"));
2079 dump_data(3, blob.data, blob.length);
2080 DEBUG(3,("secondary:\n"));
2081 dump_data(3, blob2.data, blob2.length);
2082 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
2083 "failed input validation blobs doesn't match");
2084 return ndr_map_error2ntstatus(ndr_err);
2087 return NT_STATUS_OK;
2091 this is a paranoid NDR input validator. For every packet we pull
2092 from the wire we push it back again then pull and push it
2093 again. Then we compare the raw NDR data for that to the NDR we
2094 initially generated. If they don't match then we know we must have a
2095 bug in either the pull or push side of our code
2097 static NTSTATUS dcerpc_ndr_validate_out(struct dcecli_connection *c,
2098 struct ndr_pull *pull_in,
2101 ndr_push_flags_fn_t ndr_push,
2102 ndr_pull_flags_fn_t ndr_pull,
2103 ndr_print_function_t ndr_print)
2106 struct ndr_pull *pull;
2107 struct ndr_push *push;
2108 DATA_BLOB blob, blob2;
2109 TALLOC_CTX *mem_ctx = pull_in;
2111 enum ndr_err_code ndr_err;
2113 st = talloc_size(mem_ctx, struct_size);
2115 return NT_STATUS_NO_MEMORY;
2117 memcpy(st, struct_ptr, struct_size);
2119 push = ndr_push_init_ctx(mem_ctx);
2121 return NT_STATUS_NO_MEMORY;
2124 ndr_err = ndr_push(push, NDR_OUT, struct_ptr);
2125 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2126 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2127 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2128 "failed output validation push - %s",
2130 return ndr_map_error2ntstatus(ndr_err);
2133 blob = ndr_push_blob(push);
2135 pull = ndr_pull_init_flags(c, &blob, mem_ctx);
2137 return NT_STATUS_NO_MEMORY;
2140 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
2141 ndr_err = ndr_pull(pull, NDR_OUT, st);
2142 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2143 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2144 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
2145 "failed output validation pull - %s",
2147 return ndr_map_error2ntstatus(ndr_err);
2150 push = ndr_push_init_ctx(mem_ctx);
2152 return NT_STATUS_NO_MEMORY;
2155 ndr_err = ndr_push(push, NDR_OUT, st);
2156 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2157 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2158 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2159 "failed output validation push2 - %s",
2161 return ndr_map_error2ntstatus(ndr_err);
2164 blob2 = ndr_push_blob(push);
2166 if (data_blob_cmp(&blob, &blob2) != 0) {
2167 DEBUG(3,("original:\n"));
2168 dump_data(3, blob.data, blob.length);
2169 DEBUG(3,("secondary:\n"));
2170 dump_data(3, blob2.data, blob2.length);
2171 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2172 "failed output validation blobs doesn't match");
2173 return ndr_map_error2ntstatus(ndr_err);
2176 /* this checks the printed forms of the two structures, which effectively
2177 tests all of the value() attributes */
2178 s1 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE",
2179 NDR_OUT, struct_ptr);
2180 s2 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE",
2182 if (strcmp(s1, s2) != 0) {
2184 DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1, s2));
2186 /* this is sometimes useful */
2187 printf("VALIDATE ERROR\n");
2188 file_save("wire.dat", s1, strlen(s1));
2189 file_save("gen.dat", s2, strlen(s2));
2190 system("diff -u wire.dat gen.dat");
2192 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2193 "failed output validation strings doesn't match");
2194 return ndr_map_error2ntstatus(ndr_err);
2197 return NT_STATUS_OK;
2201 a useful function for retrieving the server name we connected to
2203 _PUBLIC_ const char *dcerpc_server_name(struct dcerpc_pipe *p)
2205 return p->conn ? p->conn->server_name : NULL;
2210 get the dcerpc auth_level for a open connection
2212 uint32_t dcerpc_auth_level(struct dcecli_connection *c)
2216 if (c->flags & DCERPC_SEAL) {
2217 auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2218 } else if (c->flags & DCERPC_SIGN) {
2219 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
2220 } else if (c->flags & DCERPC_CONNECT) {
2221 auth_level = DCERPC_AUTH_LEVEL_CONNECT;
2223 auth_level = DCERPC_AUTH_LEVEL_NONE;
2228 struct dcerpc_alter_context_state {
2229 struct tevent_context *ev;
2230 struct dcerpc_pipe *p;
2233 static void dcerpc_alter_context_fail_handler(struct rpc_request *subreq);
2234 static void dcerpc_alter_context_recv_handler(struct rpc_request *req,
2235 DATA_BLOB *raw_packet,
2236 struct ncacn_packet *pkt);
2238 struct tevent_req *dcerpc_alter_context_send(TALLOC_CTX *mem_ctx,
2239 struct tevent_context *ev,
2240 struct dcerpc_pipe *p,
2241 const struct ndr_syntax_id *syntax,
2242 const struct ndr_syntax_id *transfer_syntax)
2244 struct tevent_req *req;
2245 struct dcerpc_alter_context_state *state;
2246 struct ncacn_packet pkt;
2249 struct rpc_request *subreq;
2252 req = tevent_req_create(mem_ctx, &state,
2253 struct dcerpc_alter_context_state);
2261 p->syntax = *syntax;
2262 p->transfer_syntax = *transfer_syntax;
2264 flags = dcerpc_binding_get_flags(p->binding);
2266 init_ncacn_hdr(p->conn, &pkt);
2268 pkt.ptype = DCERPC_PKT_ALTER;
2269 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
2270 pkt.call_id = p->conn->call_id;
2271 pkt.auth_length = 0;
2273 if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
2274 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
2277 pkt.u.alter.max_xmit_frag = p->conn->srv_max_xmit_frag;
2278 pkt.u.alter.max_recv_frag = p->conn->srv_max_recv_frag;
2279 pkt.u.alter.assoc_group_id = dcerpc_binding_get_assoc_group_id(p->binding);
2280 pkt.u.alter.num_contexts = 1;
2281 pkt.u.alter.ctx_list = talloc_array(state, struct dcerpc_ctx_list, 1);
2282 if (tevent_req_nomem(pkt.u.alter.ctx_list, req)) {
2283 return tevent_req_post(req, ev);
2285 pkt.u.alter.ctx_list[0].context_id = p->context_id;
2286 pkt.u.alter.ctx_list[0].num_transfer_syntaxes = 1;
2287 pkt.u.alter.ctx_list[0].abstract_syntax = p->syntax;
2288 pkt.u.alter.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
2289 pkt.u.alter.auth_info = data_blob(NULL, 0);
2291 /* construct the NDR form of the packet */
2292 status = ncacn_push_auth(&blob, state, &pkt,
2293 p->conn->security_state.tmp_auth_info.out);
2294 if (tevent_req_nterror(req, status)) {
2295 return tevent_req_post(req, ev);
2299 * we allocate a dcerpc_request so we can be in the same
2300 * request queue as normal requests
2302 subreq = talloc_zero(state, struct rpc_request);
2303 if (tevent_req_nomem(subreq, req)) {
2304 return tevent_req_post(req, ev);
2307 subreq->state = RPC_REQUEST_PENDING;
2308 subreq->call_id = pkt.call_id;
2309 subreq->async.private_data = req;
2310 subreq->async.callback = dcerpc_alter_context_fail_handler;
2312 subreq->recv_handler = dcerpc_alter_context_recv_handler;
2313 DLIST_ADD_END(p->conn->pending, subreq, struct rpc_request *);
2314 talloc_set_destructor(subreq, dcerpc_req_dequeue);
2316 status = dcerpc_send_request(p->conn, &blob, true);
2317 if (tevent_req_nterror(req, status)) {
2318 return tevent_req_post(req, ev);
2321 tevent_add_timer(ev, subreq,
2322 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
2323 dcerpc_timeout_handler, subreq);
2328 static void dcerpc_alter_context_fail_handler(struct rpc_request *subreq)
2330 struct tevent_req *req =
2331 talloc_get_type_abort(subreq->async.private_data,
2333 struct dcerpc_alter_context_state *state =
2334 tevent_req_data(req,
2335 struct dcerpc_alter_context_state);
2336 NTSTATUS status = subreq->status;
2338 TALLOC_FREE(subreq);
2341 * We trigger the callback in the next event run
2342 * because the code in this file might trigger
2343 * multiple request callbacks from within a single
2346 * In order to avoid segfaults from within
2347 * dcerpc_connection_dead() we call
2348 * tevent_req_defer_callback().
2350 tevent_req_defer_callback(req, state->ev);
2352 tevent_req_nterror(req, status);
2355 static void dcerpc_alter_context_recv_handler(struct rpc_request *subreq,
2356 DATA_BLOB *raw_packet,
2357 struct ncacn_packet *pkt)
2359 struct tevent_req *req =
2360 talloc_get_type_abort(subreq->async.private_data,
2362 struct dcerpc_alter_context_state *state =
2363 tevent_req_data(req,
2364 struct dcerpc_alter_context_state);
2365 struct dcecli_connection *conn = state->p->conn;
2366 struct dcecli_security *sec = &conn->security_state;
2370 * Note that pkt is allocated under raw_packet->data,
2371 * while raw_packet->data is a child of subreq.
2373 talloc_steal(state, raw_packet->data);
2374 TALLOC_FREE(subreq);
2377 * We trigger the callback in the next event run
2378 * because the code in this file might trigger
2379 * multiple request callbacks from within a single
2382 * In order to avoid segfaults from within
2383 * dcerpc_connection_dead() we call
2384 * tevent_req_defer_callback().
2386 tevent_req_defer_callback(req, state->ev);
2388 if (pkt->ptype == DCERPC_PKT_FAULT) {
2389 DEBUG(5,("dcerpc: alter_resp - rpc fault: %s\n",
2390 dcerpc_errstr(state, pkt->u.fault.status)));
2391 if (pkt->u.fault.status == DCERPC_FAULT_ACCESS_DENIED) {
2392 state->p->last_fault_code = pkt->u.fault.status;
2393 tevent_req_nterror(req, NT_STATUS_LOGON_FAILURE);
2394 } else if (pkt->u.fault.status == DCERPC_FAULT_SEC_PKG_ERROR) {
2395 state->p->last_fault_code = pkt->u.fault.status;
2396 tevent_req_nterror(req, NT_STATUS_LOGON_FAILURE);
2398 state->p->last_fault_code = pkt->u.fault.status;
2399 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
2400 tevent_req_nterror(req, status);
2405 status = dcerpc_verify_ncacn_packet_header(pkt,
2406 DCERPC_PKT_ALTER_RESP,
2407 pkt->u.alter_resp.auth_info.length,
2408 DCERPC_PFC_FLAG_FIRST |
2409 DCERPC_PFC_FLAG_LAST,
2410 DCERPC_PFC_FLAG_CONC_MPX |
2411 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
2412 if (!NT_STATUS_IS_OK(status)) {
2413 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
2414 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
2418 if (pkt->u.alter_resp.num_results != 1) {
2419 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
2420 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
2424 if (pkt->u.alter_resp.ctx_list[0].result != 0) {
2425 status = dcerpc_map_ack_reason(&pkt->u.alter_resp.ctx_list[0]);
2426 DEBUG(2,("dcerpc: alter_resp failed - reason %d - %s\n",
2427 pkt->u.alter_resp.ctx_list[0].reason.value,
2428 nt_errstr(status)));
2429 tevent_req_nterror(req, status);
2433 /* the alter_resp might contain a reply set of credentials */
2434 if (pkt->auth_length != 0 && sec->tmp_auth_info.in != NULL) {
2435 uint32_t auth_length;
2437 status = dcerpc_pull_auth_trailer(pkt, sec->tmp_auth_info.mem,
2438 &pkt->u.alter_resp.auth_info,
2439 sec->tmp_auth_info.in,
2440 &auth_length, true);
2441 if (tevent_req_nterror(req, status)) {
2446 tevent_req_done(req);
2449 NTSTATUS dcerpc_alter_context_recv(struct tevent_req *req)
2451 return tevent_req_simple_recv_ntstatus(req);
2455 send a dcerpc alter_context request
2457 _PUBLIC_ NTSTATUS dcerpc_alter_context(struct dcerpc_pipe *p,
2458 TALLOC_CTX *mem_ctx,
2459 const struct ndr_syntax_id *syntax,
2460 const struct ndr_syntax_id *transfer_syntax)
2462 struct tevent_req *subreq;
2463 struct tevent_context *ev = p->conn->event_ctx;
2466 /* TODO: create a new event context here */
2468 subreq = dcerpc_alter_context_send(mem_ctx, ev,
2469 p, syntax, transfer_syntax);
2470 if (subreq == NULL) {
2471 return NT_STATUS_NO_MEMORY;
2474 ok = tevent_req_poll(subreq, ev);
2477 status = map_nt_error_from_unix_common(errno);
2481 return dcerpc_alter_context_recv(subreq);
2484 static void dcerpc_transport_dead(struct dcecli_connection *c, NTSTATUS status)
2486 if (c->transport.stream == NULL) {
2490 tevent_queue_stop(c->transport.write_queue);
2491 TALLOC_FREE(c->transport.read_subreq);
2492 TALLOC_FREE(c->transport.stream);
2494 if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) {
2495 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2498 if (NT_STATUS_EQUAL(NT_STATUS_OK, status)) {
2499 status = NT_STATUS_END_OF_FILE;
2502 dcerpc_recv_data(c, NULL, status);
2507 shutdown SMB pipe connection
2509 struct dcerpc_shutdown_pipe_state {
2510 struct dcecli_connection *c;
2514 static void dcerpc_shutdown_pipe_done(struct tevent_req *subreq);
2516 static NTSTATUS dcerpc_shutdown_pipe(struct dcecli_connection *c, NTSTATUS status)
2518 struct dcerpc_shutdown_pipe_state *state;
2519 struct tevent_req *subreq;
2521 if (c->transport.stream == NULL) {
2522 return NT_STATUS_OK;
2525 state = talloc_zero(c, struct dcerpc_shutdown_pipe_state);
2526 if (state == NULL) {
2527 return NT_STATUS_NO_MEMORY;
2530 state->status = status;
2532 subreq = tstream_disconnect_send(state, c->event_ctx, c->transport.stream);
2533 if (subreq == NULL) {
2534 return NT_STATUS_NO_MEMORY;
2536 tevent_req_set_callback(subreq, dcerpc_shutdown_pipe_done, state);
2541 static void dcerpc_shutdown_pipe_done(struct tevent_req *subreq)
2543 struct dcerpc_shutdown_pipe_state *state =
2544 tevent_req_callback_data(subreq, struct dcerpc_shutdown_pipe_state);
2545 struct dcecli_connection *c = state->c;
2546 NTSTATUS status = state->status;
2550 * here we ignore the return values...
2552 tstream_disconnect_recv(subreq, &error);
2553 TALLOC_FREE(subreq);
2557 dcerpc_transport_dead(c, status);
2562 struct dcerpc_send_read_state {
2563 struct dcecli_connection *p;
2566 static int dcerpc_send_read_state_destructor(struct dcerpc_send_read_state *state)
2568 struct dcecli_connection *p = state->p;
2570 p->transport.read_subreq = NULL;
2575 static void dcerpc_send_read_done(struct tevent_req *subreq);
2577 static NTSTATUS dcerpc_send_read(struct dcecli_connection *p)
2579 struct dcerpc_send_read_state *state;
2581 if (p->transport.read_subreq != NULL) {
2582 p->transport.pending_reads++;
2583 return NT_STATUS_OK;
2586 state = talloc_zero(p, struct dcerpc_send_read_state);
2587 if (state == NULL) {
2588 return NT_STATUS_NO_MEMORY;
2592 talloc_set_destructor(state, dcerpc_send_read_state_destructor);
2594 p->transport.read_subreq = dcerpc_read_ncacn_packet_send(state,
2596 p->transport.stream);
2597 if (p->transport.read_subreq == NULL) {
2598 return NT_STATUS_NO_MEMORY;
2600 tevent_req_set_callback(p->transport.read_subreq, dcerpc_send_read_done, state);
2602 return NT_STATUS_OK;
2605 static void dcerpc_send_read_done(struct tevent_req *subreq)
2607 struct dcerpc_send_read_state *state =
2608 tevent_req_callback_data(subreq,
2609 struct dcerpc_send_read_state);
2610 struct dcecli_connection *p = state->p;
2612 struct ncacn_packet *pkt;
2615 status = dcerpc_read_ncacn_packet_recv(subreq, state,
2617 TALLOC_FREE(subreq);
2618 if (!NT_STATUS_IS_OK(status)) {
2620 dcerpc_transport_dead(p, status);
2625 * here we steal into thet connection context,
2626 * but p->transport.recv_data() will steal or free it again
2628 talloc_steal(p, blob.data);
2631 if (p->transport.pending_reads > 0) {
2632 p->transport.pending_reads--;
2634 status = dcerpc_send_read(p);
2635 if (!NT_STATUS_IS_OK(status)) {
2636 dcerpc_transport_dead(p, status);
2641 dcerpc_recv_data(p, &blob, NT_STATUS_OK);
2644 struct dcerpc_send_request_state {
2645 struct dcecli_connection *p;
2650 static int dcerpc_send_request_state_destructor(struct dcerpc_send_request_state *state)
2652 struct dcecli_connection *p = state->p;
2654 p->transport.read_subreq = NULL;
2659 static void dcerpc_send_request_wait_done(struct tevent_req *subreq);
2660 static void dcerpc_send_request_done(struct tevent_req *subreq);
2662 static NTSTATUS dcerpc_send_request(struct dcecli_connection *p, DATA_BLOB *data,
2665 struct dcerpc_send_request_state *state;
2666 struct tevent_req *subreq;
2667 bool use_trans = trigger_read;
2669 if (p->transport.stream == NULL) {
2670 return NT_STATUS_CONNECTION_DISCONNECTED;
2673 state = talloc_zero(p, struct dcerpc_send_request_state);
2674 if (state == NULL) {
2675 return NT_STATUS_NO_MEMORY;
2679 state->blob = data_blob_talloc(state, data->data, data->length);
2680 if (state->blob.data == NULL) {
2682 return NT_STATUS_NO_MEMORY;
2684 state->iov.iov_base = (void *)state->blob.data;
2685 state->iov.iov_len = state->blob.length;
2687 if (p->transport.read_subreq != NULL) {
2691 if (!tstream_is_smbXcli_np(p->transport.stream)) {
2697 * we need to block reads until our write is
2698 * the next in the write queue.
2700 p->transport.read_subreq = tevent_queue_wait_send(state, p->event_ctx,
2701 p->transport.write_queue);
2702 if (p->transport.read_subreq == NULL) {
2704 return NT_STATUS_NO_MEMORY;
2706 tevent_req_set_callback(p->transport.read_subreq,
2707 dcerpc_send_request_wait_done,
2710 talloc_set_destructor(state, dcerpc_send_request_state_destructor);
2712 trigger_read = false;
2715 subreq = tstream_writev_queue_send(state, p->event_ctx,
2716 p->transport.stream,
2717 p->transport.write_queue,
2719 if (subreq == NULL) {
2721 return NT_STATUS_NO_MEMORY;
2723 tevent_req_set_callback(subreq, dcerpc_send_request_done, state);
2726 dcerpc_send_read(p);
2729 return NT_STATUS_OK;
2732 static void dcerpc_send_request_wait_done(struct tevent_req *subreq)
2734 struct dcerpc_send_request_state *state =
2735 tevent_req_callback_data(subreq,
2736 struct dcerpc_send_request_state);
2737 struct dcecli_connection *p = state->p;
2741 p->transport.read_subreq = NULL;
2742 talloc_set_destructor(state, NULL);
2744 ok = tevent_queue_wait_recv(subreq);
2747 dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2751 if (tevent_queue_length(p->transport.write_queue) <= 2) {
2752 status = tstream_smbXcli_np_use_trans(p->transport.stream);
2753 if (!NT_STATUS_IS_OK(status)) {
2755 dcerpc_transport_dead(p, status);
2760 /* we free subreq after tstream_cli_np_use_trans */
2761 TALLOC_FREE(subreq);
2763 dcerpc_send_read(p);
2766 static void dcerpc_send_request_done(struct tevent_req *subreq)
2768 struct dcerpc_send_request_state *state =
2769 tevent_req_callback_data(subreq,
2770 struct dcerpc_send_request_state);
2774 ret = tstream_writev_queue_recv(subreq, &error);
2775 TALLOC_FREE(subreq);
2777 struct dcecli_connection *p = state->p;
2778 NTSTATUS status = map_nt_error_from_unix_common(error);
2781 dcerpc_transport_dead(p, status);