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;
158 c->max_total_response_size = DCERPC_NCACN_RESPONSE_DEFAULT_MAX_SIZE;
161 c->io_trigger = tevent_create_immediate(c);
162 if (c->io_trigger == NULL) {
167 talloc_set_destructor(c, dcerpc_connection_destructor);
172 struct dcerpc_bh_state {
173 struct dcerpc_pipe *p;
176 static bool dcerpc_bh_is_connected(struct dcerpc_binding_handle *h)
178 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
179 struct dcerpc_bh_state);
189 if (hs->p->conn->dead) {
196 static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle *h,
199 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
200 struct dcerpc_bh_state);
204 return DCERPC_REQUEST_TIMEOUT;
207 old = hs->p->request_timeout;
208 hs->p->request_timeout = timeout;
213 static void dcerpc_bh_auth_info(struct dcerpc_binding_handle *h,
214 enum dcerpc_AuthType *auth_type,
215 enum dcerpc_AuthLevel *auth_level)
217 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
218 struct dcerpc_bh_state);
224 if (hs->p->conn == NULL) {
228 *auth_type = hs->p->conn->security_state.auth_type;
229 *auth_level = hs->p->conn->security_state.auth_level;
232 struct dcerpc_bh_raw_call_state {
233 struct tevent_context *ev;
234 struct dcerpc_binding_handle *h;
240 static void dcerpc_bh_raw_call_done(struct rpc_request *subreq);
242 static struct tevent_req *dcerpc_bh_raw_call_send(TALLOC_CTX *mem_ctx,
243 struct tevent_context *ev,
244 struct dcerpc_binding_handle *h,
245 const struct GUID *object,
248 const uint8_t *in_data,
251 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
252 struct dcerpc_bh_state);
253 struct tevent_req *req;
254 struct dcerpc_bh_raw_call_state *state;
256 struct rpc_request *subreq;
258 req = tevent_req_create(mem_ctx, &state,
259 struct dcerpc_bh_raw_call_state);
265 state->in_data.data = discard_const_p(uint8_t, in_data);
266 state->in_data.length = in_length;
268 ok = dcerpc_bh_is_connected(h);
270 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
271 return tevent_req_post(req, ev);
274 subreq = dcerpc_request_send(state,
279 if (tevent_req_nomem(subreq, req)) {
280 return tevent_req_post(req, ev);
282 subreq->async.callback = dcerpc_bh_raw_call_done;
283 subreq->async.private_data = req;
288 static void dcerpc_bh_raw_call_done(struct rpc_request *subreq)
290 struct tevent_req *req =
291 talloc_get_type_abort(subreq->async.private_data,
293 struct dcerpc_bh_raw_call_state *state =
295 struct dcerpc_bh_raw_call_state);
299 state->out_flags = 0;
300 if (subreq->flags & DCERPC_PULL_BIGENDIAN) {
301 state->out_flags |= LIBNDR_FLAG_BIGENDIAN;
304 fault_code = subreq->fault_code;
306 status = dcerpc_request_recv(subreq, state, &state->out_data);
307 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
308 status = dcerpc_fault_to_nt_status(fault_code);
312 * We trigger the callback in the next event run
313 * because the code in this file might trigger
314 * multiple request callbacks from within a single
317 * In order to avoid segfaults from within
318 * dcerpc_connection_dead() we call
319 * tevent_req_defer_callback().
321 tevent_req_defer_callback(req, state->ev);
323 if (!NT_STATUS_IS_OK(status)) {
324 tevent_req_nterror(req, status);
328 tevent_req_done(req);
331 static NTSTATUS dcerpc_bh_raw_call_recv(struct tevent_req *req,
337 struct dcerpc_bh_raw_call_state *state =
339 struct dcerpc_bh_raw_call_state);
342 if (tevent_req_is_nterror(req, &status)) {
343 tevent_req_received(req);
347 *out_data = talloc_move(mem_ctx, &state->out_data.data);
348 *out_length = state->out_data.length;
349 *out_flags = state->out_flags;
350 tevent_req_received(req);
354 struct dcerpc_bh_disconnect_state {
358 static struct tevent_req *dcerpc_bh_disconnect_send(TALLOC_CTX *mem_ctx,
359 struct tevent_context *ev,
360 struct dcerpc_binding_handle *h)
362 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
363 struct dcerpc_bh_state);
364 struct tevent_req *req;
365 struct dcerpc_bh_disconnect_state *state;
368 req = tevent_req_create(mem_ctx, &state,
369 struct dcerpc_bh_disconnect_state);
374 ok = dcerpc_bh_is_connected(h);
376 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
377 return tevent_req_post(req, ev);
380 /* TODO: do a real disconnect ... */
383 tevent_req_done(req);
384 return tevent_req_post(req, ev);
387 static NTSTATUS dcerpc_bh_disconnect_recv(struct tevent_req *req)
391 if (tevent_req_is_nterror(req, &status)) {
392 tevent_req_received(req);
396 tevent_req_received(req);
400 static bool dcerpc_bh_push_bigendian(struct dcerpc_binding_handle *h)
402 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
403 struct dcerpc_bh_state);
405 if (hs->p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
412 static bool dcerpc_bh_ref_alloc(struct dcerpc_binding_handle *h)
414 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
415 struct dcerpc_bh_state);
417 if (hs->p->conn->flags & DCERPC_NDR_REF_ALLOC) {
424 static bool dcerpc_bh_use_ndr64(struct dcerpc_binding_handle *h)
426 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
427 struct dcerpc_bh_state);
429 if (hs->p->conn->flags & DCERPC_NDR64) {
436 static void dcerpc_bh_do_ndr_print(struct dcerpc_binding_handle *h,
438 const void *_struct_ptr,
439 const struct ndr_interface_call *call)
441 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
442 struct dcerpc_bh_state);
443 void *struct_ptr = discard_const(_struct_ptr);
445 if (ndr_flags & NDR_IN) {
446 if (hs->p->conn->flags & DCERPC_DEBUG_PRINT_IN) {
447 ndr_print_function_debug(call->ndr_print,
453 if (ndr_flags & NDR_OUT) {
454 if (hs->p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
455 ndr_print_function_debug(call->ndr_print,
463 static void dcerpc_bh_ndr_push_failed(struct dcerpc_binding_handle *h,
465 const void *struct_ptr,
466 const struct ndr_interface_call *call)
468 DEBUG(2,("Unable to ndr_push structure for %s - %s\n",
469 call->name, nt_errstr(error)));
472 static void dcerpc_bh_ndr_pull_failed(struct dcerpc_binding_handle *h,
474 const DATA_BLOB *blob,
475 const struct ndr_interface_call *call)
477 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
478 struct dcerpc_bh_state);
479 const uint32_t num_examples = 20;
482 DEBUG(2,("Unable to ndr_pull structure for %s - %s\n",
483 call->name, nt_errstr(error)));
485 if (hs->p->conn->packet_log_dir == NULL) return;
487 for (i=0;i<num_examples;i++) {
489 asprintf(&name, "%s/rpclog/%s-out.%d",
490 hs->p->conn->packet_log_dir,
495 if (!file_exist(name)) {
496 if (file_save(name, blob->data, blob->length)) {
497 DEBUG(10,("Logged rpc packet to %s\n", name));
506 static NTSTATUS dcerpc_bh_ndr_validate_in(struct dcerpc_binding_handle *h,
508 const DATA_BLOB *blob,
509 const struct ndr_interface_call *call)
511 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
512 struct dcerpc_bh_state);
514 if (hs->p->conn->flags & DCERPC_DEBUG_VALIDATE_IN) {
517 status = dcerpc_ndr_validate_in(hs->p->conn,
523 if (!NT_STATUS_IS_OK(status)) {
524 DEBUG(0,("Validation [in] failed for %s - %s\n",
525 call->name, nt_errstr(status)));
530 DEBUG(10,("rpc request data:\n"));
531 dump_data(10, blob->data, blob->length);
536 static NTSTATUS dcerpc_bh_ndr_validate_out(struct dcerpc_binding_handle *h,
537 struct ndr_pull *pull_in,
538 const void *_struct_ptr,
539 const struct ndr_interface_call *call)
541 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
542 struct dcerpc_bh_state);
543 void *struct_ptr = discard_const(_struct_ptr);
545 DEBUG(10,("rpc reply data:\n"));
546 dump_data(10, pull_in->data, pull_in->data_size);
548 if (pull_in->offset != pull_in->data_size) {
549 DEBUG(0,("Warning! ignoring %u unread bytes at ofs:%u (0x%08X) for %s!\n",
550 pull_in->data_size - pull_in->offset,
551 pull_in->offset, pull_in->offset,
553 /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here,
554 but it turns out that early versions of NT
555 (specifically NT3.1) add junk onto the end of rpc
556 packets, so if we want to interoperate at all with
557 those versions then we need to ignore this error */
560 if (hs->p->conn->flags & DCERPC_DEBUG_VALIDATE_OUT) {
563 status = dcerpc_ndr_validate_out(hs->p->conn,
570 if (!NT_STATUS_IS_OK(status)) {
571 DEBUG(2,("Validation [out] failed for %s - %s\n",
572 call->name, nt_errstr(status)));
580 static const struct dcerpc_binding_handle_ops dcerpc_bh_ops = {
582 .is_connected = dcerpc_bh_is_connected,
583 .set_timeout = dcerpc_bh_set_timeout,
584 .auth_info = dcerpc_bh_auth_info,
585 .raw_call_send = dcerpc_bh_raw_call_send,
586 .raw_call_recv = dcerpc_bh_raw_call_recv,
587 .disconnect_send = dcerpc_bh_disconnect_send,
588 .disconnect_recv = dcerpc_bh_disconnect_recv,
590 .push_bigendian = dcerpc_bh_push_bigendian,
591 .ref_alloc = dcerpc_bh_ref_alloc,
592 .use_ndr64 = dcerpc_bh_use_ndr64,
593 .do_ndr_print = dcerpc_bh_do_ndr_print,
594 .ndr_push_failed = dcerpc_bh_ndr_push_failed,
595 .ndr_pull_failed = dcerpc_bh_ndr_pull_failed,
596 .ndr_validate_in = dcerpc_bh_ndr_validate_in,
597 .ndr_validate_out = dcerpc_bh_ndr_validate_out,
600 /* initialise a dcerpc pipe. */
601 struct dcerpc_binding_handle *dcerpc_pipe_binding_handle(struct dcerpc_pipe *p)
603 struct dcerpc_binding_handle *h;
604 struct dcerpc_bh_state *hs;
606 h = dcerpc_binding_handle_create(p,
611 struct dcerpc_bh_state,
618 dcerpc_binding_handle_set_sync_ev(h, p->conn->event_ctx);
623 /* initialise a dcerpc pipe. */
624 _PUBLIC_ struct dcerpc_pipe *dcerpc_pipe_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev)
626 struct dcerpc_pipe *p;
628 p = talloc_zero(mem_ctx, struct dcerpc_pipe);
633 p->conn = dcerpc_connection_init(p, ev);
634 if (p->conn == NULL) {
639 p->last_fault_code = 0;
641 p->request_timeout = DCERPC_REQUEST_TIMEOUT;
644 ZERO_STRUCT(p->syntax);
645 ZERO_STRUCT(p->transfer_syntax);
648 p->conn->flags |= DCERPC_DEBUG_PRINT_BOTH;
651 p->binding_handle = dcerpc_pipe_binding_handle(p);
652 if (p->binding_handle == NULL) {
662 choose the next call id to use
664 static uint32_t next_call_id(struct dcecli_connection *c)
667 if (c->call_id == 0) {
674 setup for a ndr pull, also setting up any flags from the binding string
676 static struct ndr_pull *ndr_pull_init_flags(struct dcecli_connection *c,
677 DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
679 struct ndr_pull *ndr = ndr_pull_init_blob(blob, mem_ctx);
681 if (ndr == NULL) return ndr;
683 if (c->flags & DCERPC_DEBUG_PAD_CHECK) {
684 ndr->flags |= LIBNDR_FLAG_PAD_CHECK;
687 if (c->flags & DCERPC_NDR_REF_ALLOC) {
688 ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
691 if (c->flags & DCERPC_NDR64) {
692 ndr->flags |= LIBNDR_FLAG_NDR64;
699 parse a data blob into a ncacn_packet structure. This handles both
700 input and output packets
702 static NTSTATUS ncacn_pull(struct dcecli_connection *c, DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
703 struct ncacn_packet *pkt)
705 struct ndr_pull *ndr;
706 enum ndr_err_code ndr_err;
708 ndr = ndr_pull_init_blob(blob, mem_ctx);
710 return NT_STATUS_NO_MEMORY;
713 if (! (CVAL(blob->data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) {
714 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
717 if (CVAL(blob->data, DCERPC_PFC_OFFSET) & DCERPC_PFC_FLAG_OBJECT_UUID) {
718 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
721 ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
723 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
724 return ndr_map_error2ntstatus(ndr_err);
727 if (pkt->frag_length != blob->length) {
728 return NT_STATUS_RPC_PROTOCOL_ERROR;
735 parse the authentication information on a dcerpc response packet
737 static NTSTATUS ncacn_pull_request_auth(struct dcecli_connection *c, TALLOC_CTX *mem_ctx,
738 DATA_BLOB *raw_packet,
739 struct ncacn_packet *pkt)
742 struct dcerpc_auth auth;
743 uint32_t auth_length;
745 status = dcerpc_verify_ncacn_packet_header(pkt, DCERPC_PKT_RESPONSE,
746 pkt->u.response.stub_and_verifier.length,
747 0, /* required_flags */
748 DCERPC_PFC_FLAG_FIRST |
749 DCERPC_PFC_FLAG_LAST);
750 if (!NT_STATUS_IS_OK(status)) {
754 switch (c->security_state.auth_level) {
755 case DCERPC_AUTH_LEVEL_PRIVACY:
756 case DCERPC_AUTH_LEVEL_INTEGRITY:
759 case DCERPC_AUTH_LEVEL_CONNECT:
760 if (pkt->auth_length != 0) {
764 case DCERPC_AUTH_LEVEL_NONE:
765 if (pkt->auth_length != 0) {
766 return NT_STATUS_INVALID_NETWORK_RESPONSE;
771 return NT_STATUS_INVALID_LEVEL;
774 if (pkt->auth_length == 0) {
775 return NT_STATUS_INVALID_NETWORK_RESPONSE;
778 if (c->security_state.generic_state == NULL) {
779 return NT_STATUS_INTERNAL_ERROR;
782 status = dcerpc_pull_auth_trailer(pkt, mem_ctx,
783 &pkt->u.response.stub_and_verifier,
784 &auth, &auth_length, false);
785 NT_STATUS_NOT_OK_RETURN(status);
787 pkt->u.response.stub_and_verifier.length -= auth_length;
789 if (auth.auth_type != c->security_state.auth_type) {
790 return NT_STATUS_RPC_PROTOCOL_ERROR;
793 if (auth.auth_level != c->security_state.auth_level) {
794 return NT_STATUS_RPC_PROTOCOL_ERROR;
797 if (auth.auth_context_id != c->security_state.auth_context_id) {
798 return NT_STATUS_RPC_PROTOCOL_ERROR;
801 /* check signature or unseal the packet */
802 switch (c->security_state.auth_level) {
803 case DCERPC_AUTH_LEVEL_PRIVACY:
804 status = gensec_unseal_packet(c->security_state.generic_state,
805 raw_packet->data + DCERPC_REQUEST_LENGTH,
806 pkt->u.response.stub_and_verifier.length,
808 raw_packet->length - auth.credentials.length,
810 memcpy(pkt->u.response.stub_and_verifier.data,
811 raw_packet->data + DCERPC_REQUEST_LENGTH,
812 pkt->u.response.stub_and_verifier.length);
815 case DCERPC_AUTH_LEVEL_INTEGRITY:
816 status = gensec_check_packet(c->security_state.generic_state,
817 pkt->u.response.stub_and_verifier.data,
818 pkt->u.response.stub_and_verifier.length,
820 raw_packet->length - auth.credentials.length,
824 case DCERPC_AUTH_LEVEL_CONNECT:
825 /* for now we ignore possible signatures here */
826 status = NT_STATUS_OK;
830 status = NT_STATUS_INVALID_LEVEL;
834 /* remove the indicated amount of padding */
835 if (pkt->u.response.stub_and_verifier.length < auth.auth_pad_length) {
836 return NT_STATUS_INFO_LENGTH_MISMATCH;
838 pkt->u.response.stub_and_verifier.length -= auth.auth_pad_length;
845 push a dcerpc request packet into a blob, possibly signing it.
847 static NTSTATUS ncacn_push_request_sign(struct dcecli_connection *c,
848 DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
850 struct ncacn_packet *pkt)
853 struct ndr_push *ndr;
855 size_t payload_length;
856 enum ndr_err_code ndr_err;
857 size_t hdr_size = DCERPC_REQUEST_LENGTH;
858 struct dcerpc_auth auth_info = {
859 .auth_type = c->security_state.auth_type,
860 .auth_level = c->security_state.auth_level,
861 .auth_context_id = c->security_state.auth_context_id,
864 switch (c->security_state.auth_level) {
865 case DCERPC_AUTH_LEVEL_PRIVACY:
866 case DCERPC_AUTH_LEVEL_INTEGRITY:
868 return NT_STATUS_INTERNAL_ERROR;
872 case DCERPC_AUTH_LEVEL_CONNECT:
873 /* TODO: let the gensec mech decide if it wants to generate a signature */
874 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
876 case DCERPC_AUTH_LEVEL_NONE:
877 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
880 return NT_STATUS_INVALID_LEVEL;
883 ndr = ndr_push_init_ctx(mem_ctx);
885 return NT_STATUS_NO_MEMORY;
888 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
889 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
892 if (c->flags & DCERPC_NDR64) {
893 ndr->flags |= LIBNDR_FLAG_NDR64;
896 if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
897 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
901 ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
902 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
903 return ndr_map_error2ntstatus(ndr_err);
906 /* pad to 16 byte multiple in the payload portion of the
907 packet. This matches what w2k3 does. Note that we can't use
908 ndr_push_align() as that is relative to the start of the
909 whole packet, whereas w2k8 wants it relative to the start
911 auth_info.auth_pad_length =
912 DCERPC_AUTH_PAD_LENGTH(pkt->u.request.stub_and_verifier.length);
913 ndr_err = ndr_push_zero(ndr, auth_info.auth_pad_length);
914 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
915 return ndr_map_error2ntstatus(ndr_err);
918 payload_length = pkt->u.request.stub_and_verifier.length +
919 auth_info.auth_pad_length;
921 /* add the auth verifier */
922 ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, &auth_info);
923 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
924 return ndr_map_error2ntstatus(ndr_err);
927 /* extract the whole packet as a blob */
928 *blob = ndr_push_blob(ndr);
931 * Setup the frag and auth length in the packet buffer.
932 * This is needed if the GENSEC mech does AEAD signing
933 * of the packet headers. The signature itself will be
936 dcerpc_set_frag_length(blob, blob->length + sig_size);
937 dcerpc_set_auth_length(blob, sig_size);
939 /* sign or seal the packet */
940 switch (c->security_state.auth_level) {
941 case DCERPC_AUTH_LEVEL_PRIVACY:
942 status = gensec_seal_packet(c->security_state.generic_state,
944 blob->data + hdr_size,
949 if (!NT_STATUS_IS_OK(status)) {
954 case DCERPC_AUTH_LEVEL_INTEGRITY:
955 status = gensec_sign_packet(c->security_state.generic_state,
957 blob->data + hdr_size,
962 if (!NT_STATUS_IS_OK(status)) {
968 status = NT_STATUS_INVALID_LEVEL;
972 if (creds2.length != sig_size) {
973 /* this means the sig_size estimate for the signature
974 was incorrect. We have to correct the packet
975 sizes. That means we could go over the max fragment
977 DEBUG(3,("ncacn_push_request_sign: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n",
978 (unsigned) creds2.length,
980 (unsigned) auth_info.auth_pad_length,
981 (unsigned) pkt->u.request.stub_and_verifier.length));
982 dcerpc_set_frag_length(blob, blob->length + creds2.length);
983 dcerpc_set_auth_length(blob, creds2.length);
986 if (!data_blob_append(mem_ctx, blob, creds2.data, creds2.length)) {
987 return NT_STATUS_NO_MEMORY;
995 fill in the fixed values in a dcerpc header
997 static void init_ncacn_hdr(struct dcecli_connection *c, struct ncacn_packet *pkt)
1000 pkt->rpc_vers_minor = 0;
1001 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
1004 pkt->drep[0] = DCERPC_DREP_LE;
1012 map a bind nak reason to a NTSTATUS
1014 static NTSTATUS dcerpc_map_nak_reason(enum dcerpc_bind_nak_reason reason)
1017 case DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED:
1018 return NT_STATUS_REVISION_MISMATCH;
1019 case DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE:
1020 return NT_STATUS_INVALID_PARAMETER;
1024 return NT_STATUS_UNSUCCESSFUL;
1027 static NTSTATUS dcerpc_map_ack_reason(const struct dcerpc_ack_ctx *ack)
1030 return NT_STATUS_RPC_PROTOCOL_ERROR;
1033 switch (ack->result) {
1034 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
1036 * We have not asked for this...
1038 return NT_STATUS_RPC_PROTOCOL_ERROR;
1043 switch (ack->reason.value) {
1044 case DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED:
1045 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
1046 case DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED:
1047 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
1051 return NT_STATUS_UNSUCCESSFUL;
1055 remove requests from the pending or queued queues
1057 static int dcerpc_req_dequeue(struct rpc_request *req)
1059 switch (req->state) {
1060 case RPC_REQUEST_QUEUED:
1061 DLIST_REMOVE(req->p->conn->request_queue, req);
1063 case RPC_REQUEST_PENDING:
1064 DLIST_REMOVE(req->p->conn->pending, req);
1066 case RPC_REQUEST_DONE:
1074 mark the dcerpc connection dead. All outstanding requests get an error
1076 static void dcerpc_connection_dead(struct dcecli_connection *conn, NTSTATUS status)
1078 if (conn->dead) return;
1082 TALLOC_FREE(conn->io_trigger);
1083 conn->io_trigger_pending = false;
1085 dcerpc_shutdown_pipe(conn, status);
1087 /* all pending requests get the error */
1088 while (conn->pending) {
1089 struct rpc_request *req = conn->pending;
1090 dcerpc_req_dequeue(req);
1091 req->state = RPC_REQUEST_DONE;
1092 req->status = status;
1093 if (req->async.callback) {
1094 req->async.callback(req);
1098 /* all requests, which are not shipped */
1099 while (conn->request_queue) {
1100 struct rpc_request *req = conn->request_queue;
1101 dcerpc_req_dequeue(req);
1102 req->state = RPC_REQUEST_DONE;
1103 req->status = status;
1104 if (req->async.callback) {
1105 req->async.callback(req);
1109 talloc_set_destructor(conn, NULL);
1110 if (conn->free_skipped) {
1116 forward declarations of the recv_data handlers for the types of
1117 packets we need to handle
1119 static void dcerpc_request_recv_data(struct dcecli_connection *c,
1120 DATA_BLOB *raw_packet, struct ncacn_packet *pkt);
1123 receive a dcerpc reply from the transport. Here we work out what
1124 type of reply it is (normal request, bind or alter context) and
1125 dispatch to the appropriate handler
1127 static void dcerpc_recv_data(struct dcecli_connection *conn, DATA_BLOB *blob, NTSTATUS status)
1129 struct ncacn_packet pkt;
1135 if (NT_STATUS_IS_OK(status) && blob->length == 0) {
1136 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1139 /* the transport may be telling us of a severe error, such as
1141 if (!NT_STATUS_IS_OK(status)) {
1142 data_blob_free(blob);
1143 dcerpc_connection_dead(conn, status);
1147 /* parse the basic packet to work out what type of response this is */
1148 status = ncacn_pull(conn, blob, blob->data, &pkt);
1149 if (!NT_STATUS_IS_OK(status)) {
1150 data_blob_free(blob);
1151 dcerpc_connection_dead(conn, status);
1155 dcerpc_request_recv_data(conn, blob, &pkt);
1159 handle timeouts of individual dcerpc requests
1161 static void dcerpc_timeout_handler(struct tevent_context *ev, struct tevent_timer *te,
1162 struct timeval t, void *private_data)
1164 struct rpc_request *req = talloc_get_type(private_data, struct rpc_request);
1166 if (req->ignore_timeout) {
1167 dcerpc_req_dequeue(req);
1168 req->state = RPC_REQUEST_DONE;
1169 req->status = NT_STATUS_IO_TIMEOUT;
1170 if (req->async.callback) {
1171 req->async.callback(req);
1176 dcerpc_connection_dead(req->p->conn, NT_STATUS_IO_TIMEOUT);
1179 struct dcerpc_bind_state {
1180 struct tevent_context *ev;
1181 struct dcerpc_pipe *p;
1184 static void dcerpc_bind_fail_handler(struct rpc_request *subreq);
1185 static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
1186 DATA_BLOB *raw_packet,
1187 struct ncacn_packet *pkt);
1189 struct tevent_req *dcerpc_bind_send(TALLOC_CTX *mem_ctx,
1190 struct tevent_context *ev,
1191 struct dcerpc_pipe *p,
1192 const struct ndr_syntax_id *syntax,
1193 const struct ndr_syntax_id *transfer_syntax)
1195 struct tevent_req *req;
1196 struct dcerpc_bind_state *state;
1197 struct ncacn_packet pkt;
1200 struct rpc_request *subreq;
1203 req = tevent_req_create(mem_ctx, &state,
1204 struct dcerpc_bind_state);
1212 p->syntax = *syntax;
1213 p->transfer_syntax = *transfer_syntax;
1215 flags = dcerpc_binding_get_flags(p->binding);
1217 init_ncacn_hdr(p->conn, &pkt);
1219 pkt.ptype = DCERPC_PKT_BIND;
1220 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1221 pkt.call_id = p->conn->call_id;
1222 pkt.auth_length = 0;
1224 if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
1225 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1228 if (p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) {
1229 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1232 pkt.u.bind.max_xmit_frag = p->conn->srv_max_xmit_frag;
1233 pkt.u.bind.max_recv_frag = p->conn->srv_max_recv_frag;
1234 pkt.u.bind.assoc_group_id = dcerpc_binding_get_assoc_group_id(p->binding);
1235 pkt.u.bind.num_contexts = 1;
1236 pkt.u.bind.ctx_list = talloc_array(mem_ctx, struct dcerpc_ctx_list, 1);
1237 if (tevent_req_nomem(pkt.u.bind.ctx_list, req)) {
1238 return tevent_req_post(req, ev);
1240 pkt.u.bind.ctx_list[0].context_id = p->context_id;
1241 pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1;
1242 pkt.u.bind.ctx_list[0].abstract_syntax = p->syntax;
1243 pkt.u.bind.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
1244 pkt.u.bind.auth_info = data_blob(NULL, 0);
1246 /* construct the NDR form of the packet */
1247 status = ncacn_push_auth(&blob, state, &pkt,
1248 p->conn->security_state.tmp_auth_info.out);
1249 if (tevent_req_nterror(req, status)) {
1250 return tevent_req_post(req, ev);
1254 * we allocate a dcerpc_request so we can be in the same
1255 * request queue as normal requests
1257 subreq = talloc_zero(state, struct rpc_request);
1258 if (tevent_req_nomem(subreq, req)) {
1259 return tevent_req_post(req, ev);
1262 subreq->state = RPC_REQUEST_PENDING;
1263 subreq->call_id = pkt.call_id;
1264 subreq->async.private_data = req;
1265 subreq->async.callback = dcerpc_bind_fail_handler;
1267 subreq->recv_handler = dcerpc_bind_recv_handler;
1268 DLIST_ADD_END(p->conn->pending, subreq, struct rpc_request *);
1269 talloc_set_destructor(subreq, dcerpc_req_dequeue);
1271 status = dcerpc_send_request(p->conn, &blob, true);
1272 if (tevent_req_nterror(req, status)) {
1273 return tevent_req_post(req, ev);
1276 tevent_add_timer(ev, subreq,
1277 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
1278 dcerpc_timeout_handler, subreq);
1283 static void dcerpc_bind_fail_handler(struct rpc_request *subreq)
1285 struct tevent_req *req =
1286 talloc_get_type_abort(subreq->async.private_data,
1288 struct dcerpc_bind_state *state =
1289 tevent_req_data(req,
1290 struct dcerpc_bind_state);
1291 NTSTATUS status = subreq->status;
1293 TALLOC_FREE(subreq);
1296 * We trigger the callback in the next event run
1297 * because the code in this file might trigger
1298 * multiple request callbacks from within a single
1301 * In order to avoid segfaults from within
1302 * dcerpc_connection_dead() we call
1303 * tevent_req_defer_callback().
1305 tevent_req_defer_callback(req, state->ev);
1307 tevent_req_nterror(req, status);
1310 static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
1311 DATA_BLOB *raw_packet,
1312 struct ncacn_packet *pkt)
1314 struct tevent_req *req =
1315 talloc_get_type_abort(subreq->async.private_data,
1317 struct dcerpc_bind_state *state =
1318 tevent_req_data(req,
1319 struct dcerpc_bind_state);
1320 struct dcecli_connection *conn = state->p->conn;
1321 struct dcecli_security *sec = &conn->security_state;
1322 struct dcerpc_binding *b = NULL;
1327 * Note that pkt is allocated under raw_packet->data,
1328 * while raw_packet->data is a child of subreq.
1330 talloc_steal(state, raw_packet->data);
1331 TALLOC_FREE(subreq);
1334 * We trigger the callback in the next event run
1335 * because the code in this file might trigger
1336 * multiple request callbacks from within a single
1339 * In order to avoid segfaults from within
1340 * dcerpc_connection_dead() we call
1341 * tevent_req_defer_callback().
1343 tevent_req_defer_callback(req, state->ev);
1345 if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
1346 status = dcerpc_map_nak_reason(pkt->u.bind_nak.reject_reason);
1348 DEBUG(2,("dcerpc: bind_nak reason %d - %s\n",
1349 pkt->u.bind_nak.reject_reason, nt_errstr(status)));
1351 tevent_req_nterror(req, status);
1355 status = dcerpc_verify_ncacn_packet_header(pkt,
1356 DCERPC_PKT_BIND_ACK,
1357 pkt->u.bind_ack.auth_info.length,
1358 DCERPC_PFC_FLAG_FIRST |
1359 DCERPC_PFC_FLAG_LAST,
1360 DCERPC_PFC_FLAG_CONC_MPX |
1361 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
1362 if (!NT_STATUS_IS_OK(status)) {
1363 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1364 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1368 if (pkt->u.bind_ack.num_results != 1) {
1369 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1370 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1374 if (pkt->u.bind_ack.ctx_list[0].result != 0) {
1375 status = dcerpc_map_ack_reason(&pkt->u.bind_ack.ctx_list[0]);
1376 DEBUG(2,("dcerpc: bind_ack failed - reason %d - %s\n",
1377 pkt->u.bind_ack.ctx_list[0].reason.value,
1378 nt_errstr(status)));
1379 tevent_req_nterror(req, status);
1384 * DCE-RPC 1.1 (c706) specifies
1385 * CONST_MUST_RCV_FRAG_SIZE as 1432
1387 if (pkt->u.bind_ack.max_xmit_frag < 1432) {
1388 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1389 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1392 if (pkt->u.bind_ack.max_recv_frag < 1432) {
1393 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1394 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1397 conn->srv_max_xmit_frag = MIN(conn->srv_max_xmit_frag,
1398 pkt->u.bind_ack.max_xmit_frag);
1399 conn->srv_max_recv_frag = MIN(conn->srv_max_recv_frag,
1400 pkt->u.bind_ack.max_recv_frag);
1402 flags = dcerpc_binding_get_flags(state->p->binding);
1404 if ((flags & DCERPC_CONCURRENT_MULTIPLEX) &&
1405 (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX)) {
1406 conn->flags |= DCERPC_CONCURRENT_MULTIPLEX;
1409 if ((conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) &&
1410 (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
1411 conn->flags |= DCERPC_HEADER_SIGNING;
1414 /* the bind_ack might contain a reply set of credentials */
1415 if (pkt->auth_length != 0 && sec->tmp_auth_info.in != NULL) {
1416 uint32_t auth_length;
1418 status = dcerpc_pull_auth_trailer(pkt, sec->tmp_auth_info.mem,
1419 &pkt->u.bind_ack.auth_info,
1420 sec->tmp_auth_info.in,
1421 &auth_length, true);
1422 if (tevent_req_nterror(req, status)) {
1428 * We're the owner of the binding, so we're allowed to modify it.
1430 b = discard_const_p(struct dcerpc_binding, state->p->binding);
1431 status = dcerpc_binding_set_assoc_group_id(b,
1432 pkt->u.bind_ack.assoc_group_id);
1433 if (tevent_req_nterror(req, status)) {
1437 tevent_req_done(req);
1440 NTSTATUS dcerpc_bind_recv(struct tevent_req *req)
1442 return tevent_req_simple_recv_ntstatus(req);
1446 perform a continued bind (and auth3)
1448 NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p,
1449 TALLOC_CTX *mem_ctx)
1451 struct ncacn_packet pkt;
1456 flags = dcerpc_binding_get_flags(p->binding);
1458 init_ncacn_hdr(p->conn, &pkt);
1460 pkt.ptype = DCERPC_PKT_AUTH3;
1461 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1462 pkt.call_id = next_call_id(p->conn);
1463 pkt.auth_length = 0;
1464 pkt.u.auth3.auth_info = data_blob(NULL, 0);
1466 if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
1467 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1470 /* construct the NDR form of the packet */
1471 status = ncacn_push_auth(&blob, mem_ctx, &pkt,
1472 p->conn->security_state.tmp_auth_info.out);
1473 if (!NT_STATUS_IS_OK(status)) {
1477 /* send it on its way */
1478 status = dcerpc_send_request(p->conn, &blob, false);
1479 if (!NT_STATUS_IS_OK(status)) {
1483 return NT_STATUS_OK;
1488 process a fragment received from the transport layer during a
1491 This function frees the data
1493 static void dcerpc_request_recv_data(struct dcecli_connection *c,
1494 DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
1496 struct rpc_request *req;
1497 unsigned int length;
1498 NTSTATUS status = NT_STATUS_OK;
1501 if this is an authenticated connection then parse and check
1502 the auth info. We have to do this before finding the
1503 matching packet, as the request structure might have been
1504 removed due to a timeout, but if it has been we still need
1505 to run the auth routines so that we don't get the sign/seal
1506 info out of step with the server
1508 if (pkt->ptype == DCERPC_PKT_RESPONSE) {
1509 status = ncacn_pull_request_auth(c, raw_packet->data, raw_packet, pkt);
1512 /* find the matching request */
1513 for (req=c->pending;req;req=req->next) {
1514 if (pkt->call_id == req->call_id) break;
1518 /* useful for testing certain vendors RPC servers */
1519 if (req == NULL && c->pending && pkt->call_id == 0) {
1520 DEBUG(0,("HACK FOR INCORRECT CALL ID\n"));
1526 DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt->call_id));
1527 data_blob_free(raw_packet);
1531 talloc_steal(req, raw_packet->data);
1533 if (req->recv_handler != NULL) {
1534 dcerpc_req_dequeue(req);
1535 req->state = RPC_REQUEST_DONE;
1538 * We have to look at shipping further requests before calling
1539 * the async function, that one might close the pipe
1541 dcerpc_schedule_io_trigger(c);
1543 req->recv_handler(req, raw_packet, pkt);
1547 if (pkt->ptype == DCERPC_PKT_FAULT) {
1548 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
1549 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
1550 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
1551 dcerpc_connection_dead(c, status);
1554 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
1555 dcerpc_connection_dead(c, status);
1558 req->fault_code = pkt->u.fault.status;
1559 req->status = NT_STATUS_NET_WRITE_FAULT;
1563 if (pkt->ptype != DCERPC_PKT_RESPONSE) {
1564 DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
1566 dcerpc_connection_dead(c, NT_STATUS_RPC_PROTOCOL_ERROR);
1570 /* now check the status from the auth routines, and if it failed then fail
1571 this request accordingly */
1572 if (!NT_STATUS_IS_OK(status)) {
1573 dcerpc_connection_dead(c, status);
1577 length = pkt->u.response.stub_and_verifier.length;
1579 if (req->payload.length + length > c->max_total_response_size) {
1580 DEBUG(2,("Unexpected total payload 0x%X > 0x%X dcerpc response\n",
1581 (unsigned)req->payload.length + length,
1582 (unsigned)c->max_total_response_size));
1583 dcerpc_connection_dead(c, NT_STATUS_RPC_PROTOCOL_ERROR);
1588 req->payload.data = talloc_realloc(req,
1591 req->payload.length + length);
1592 if (!req->payload.data) {
1593 req->status = NT_STATUS_NO_MEMORY;
1596 memcpy(req->payload.data+req->payload.length,
1597 pkt->u.response.stub_and_verifier.data, length);
1598 req->payload.length += length;
1601 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1602 data_blob_free(raw_packet);
1603 dcerpc_send_read(c);
1607 if (req->verify_bitmask1) {
1608 req->p->conn->security_state.verified_bitmask1 = true;
1610 if (req->verify_pcontext) {
1611 req->p->verified_pcontext = true;
1614 if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
1615 req->flags |= DCERPC_PULL_BIGENDIAN;
1617 req->flags &= ~DCERPC_PULL_BIGENDIAN;
1621 data_blob_free(raw_packet);
1623 /* we've got the full payload */
1624 dcerpc_req_dequeue(req);
1625 req->state = RPC_REQUEST_DONE;
1628 * We have to look at shipping further requests before calling
1629 * the async function, that one might close the pipe
1631 dcerpc_schedule_io_trigger(c);
1633 if (req->async.callback) {
1634 req->async.callback(req);
1638 static NTSTATUS dcerpc_request_prepare_vt(struct rpc_request *req);
1641 perform the send side of a async dcerpc request
1643 static struct rpc_request *dcerpc_request_send(TALLOC_CTX *mem_ctx,
1644 struct dcerpc_pipe *p,
1645 const struct GUID *object,
1647 DATA_BLOB *stub_data)
1649 struct rpc_request *req;
1652 req = talloc_zero(mem_ctx, struct rpc_request);
1658 req->call_id = next_call_id(p->conn);
1659 req->state = RPC_REQUEST_QUEUED;
1661 if (object != NULL) {
1662 req->object = (struct GUID *)talloc_memdup(req, (const void *)object, sizeof(*object));
1663 if (req->object == NULL) {
1670 req->request_data.length = stub_data->length;
1671 req->request_data.data = stub_data->data;
1673 status = dcerpc_request_prepare_vt(req);
1674 if (!NT_STATUS_IS_OK(status)) {
1679 DLIST_ADD_END(p->conn->request_queue, req, struct rpc_request *);
1680 talloc_set_destructor(req, dcerpc_req_dequeue);
1682 dcerpc_schedule_io_trigger(p->conn);
1684 if (p->request_timeout) {
1685 tevent_add_timer(p->conn->event_ctx, req,
1686 timeval_current_ofs(p->request_timeout, 0),
1687 dcerpc_timeout_handler, req);
1693 static NTSTATUS dcerpc_request_prepare_vt(struct rpc_request *req)
1695 struct dcecli_security *sec = &req->p->conn->security_state;
1696 struct dcerpc_sec_verification_trailer *t;
1697 struct dcerpc_sec_vt *c = NULL;
1698 struct ndr_push *ndr = NULL;
1699 enum ndr_err_code ndr_err;
1701 if (sec->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1702 return NT_STATUS_OK;
1705 t = talloc_zero(req, struct dcerpc_sec_verification_trailer);
1707 return NT_STATUS_NO_MEMORY;
1710 if (!sec->verified_bitmask1) {
1711 t->commands = talloc_realloc(t, t->commands,
1712 struct dcerpc_sec_vt,
1713 t->count.count + 1);
1714 if (t->commands == NULL) {
1715 return NT_STATUS_NO_MEMORY;
1717 c = &t->commands[t->count.count++];
1720 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1721 if (req->p->conn->flags & DCERPC_PROPOSE_HEADER_SIGNING) {
1722 c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1724 req->verify_bitmask1 = true;
1727 if (!req->p->verified_pcontext) {
1728 t->commands = talloc_realloc(t, t->commands,
1729 struct dcerpc_sec_vt,
1730 t->count.count + 1);
1731 if (t->commands == NULL) {
1732 return NT_STATUS_NO_MEMORY;
1734 c = &t->commands[t->count.count++];
1737 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1738 c->u.pcontext.abstract_syntax = req->p->syntax;
1739 c->u.pcontext.transfer_syntax = req->p->transfer_syntax;
1741 req->verify_pcontext = true;
1744 if (!(req->p->conn->flags & DCERPC_HEADER_SIGNING)) {
1745 t->commands = talloc_realloc(t, t->commands,
1746 struct dcerpc_sec_vt,
1747 t->count.count + 1);
1748 if (t->commands == NULL) {
1749 return NT_STATUS_NO_MEMORY;
1751 c = &t->commands[t->count.count++];
1754 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1755 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1756 if (req->p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
1757 c->u.header2.drep[0] = 0;
1759 c->u.header2.drep[0] = DCERPC_DREP_LE;
1761 c->u.header2.drep[1] = 0;
1762 c->u.header2.drep[2] = 0;
1763 c->u.header2.drep[3] = 0;
1764 c->u.header2.call_id = req->call_id;
1765 c->u.header2.context_id = req->p->context_id;
1766 c->u.header2.opnum = req->opnum;
1769 if (t->count.count == 0) {
1771 return NT_STATUS_OK;
1774 c = &t->commands[t->count.count - 1];
1775 c->command |= DCERPC_SEC_VT_COMMAND_END;
1777 if (DEBUGLEVEL >= 10) {
1778 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1781 ndr = ndr_push_init_ctx(req);
1783 return NT_STATUS_NO_MEMORY;
1787 * for now we just copy and append
1790 ndr_err = ndr_push_bytes(ndr, req->request_data.data,
1791 req->request_data.length);
1792 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1793 return ndr_map_error2ntstatus(ndr_err);
1796 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1797 NDR_SCALARS | NDR_BUFFERS,
1799 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1800 return ndr_map_error2ntstatus(ndr_err);
1802 req->request_data = ndr_push_blob(ndr);
1804 return NT_STATUS_OK;
1808 Send a request using the transport
1811 static void dcerpc_ship_next_request(struct dcecli_connection *c)
1813 struct rpc_request *req;
1814 struct dcerpc_pipe *p;
1815 DATA_BLOB *stub_data;
1816 struct ncacn_packet pkt;
1818 uint32_t remaining, chunk_size;
1819 bool first_packet = true;
1820 size_t sig_size = 0;
1821 bool need_async = false;
1822 bool can_async = true;
1824 req = c->request_queue;
1830 stub_data = &req->request_data;
1836 if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1837 can_async = gensec_have_feature(c->security_state.generic_state,
1838 GENSEC_FEATURE_ASYNC_REPLIES);
1841 if (need_async && !can_async) {
1842 req->wait_for_sync = true;
1846 DLIST_REMOVE(c->request_queue, req);
1847 DLIST_ADD(c->pending, req);
1848 req->state = RPC_REQUEST_PENDING;
1850 init_ncacn_hdr(p->conn, &pkt);
1852 remaining = stub_data->length;
1854 /* we can write a full max_recv_frag size, minus the dcerpc
1855 request header size */
1856 chunk_size = p->conn->srv_max_recv_frag;
1857 chunk_size -= DCERPC_REQUEST_LENGTH;
1858 if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1859 size_t max_payload = chunk_size;
1861 max_payload -= DCERPC_AUTH_TRAILER_LENGTH;
1862 max_payload -= (max_payload % DCERPC_AUTH_PAD_ALIGNMENT);
1864 sig_size = gensec_sig_size(c->security_state.generic_state,
1867 chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
1868 chunk_size -= sig_size;
1871 chunk_size -= (chunk_size % DCERPC_AUTH_PAD_ALIGNMENT);
1873 pkt.ptype = DCERPC_PKT_REQUEST;
1874 pkt.call_id = req->call_id;
1875 pkt.auth_length = 0;
1877 pkt.u.request.context_id = p->context_id;
1878 pkt.u.request.opnum = req->opnum;
1881 pkt.u.request.object.object = *req->object;
1882 pkt.pfc_flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1883 chunk_size -= ndr_size_GUID(req->object,0);
1886 /* we send a series of pdus without waiting for a reply */
1887 while (remaining > 0 || first_packet) {
1888 uint32_t chunk = MIN(chunk_size, remaining);
1889 bool last_frag = false;
1890 bool do_trans = false;
1892 first_packet = false;
1893 pkt.pfc_flags &= ~(DCERPC_PFC_FLAG_FIRST |DCERPC_PFC_FLAG_LAST);
1895 if (remaining == stub_data->length) {
1896 pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST;
1898 if (chunk == remaining) {
1899 pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
1903 pkt.u.request.alloc_hint = remaining;
1904 pkt.u.request.stub_and_verifier.data = stub_data->data +
1905 (stub_data->length - remaining);
1906 pkt.u.request.stub_and_verifier.length = chunk;
1908 req->status = ncacn_push_request_sign(p->conn, &blob, req, sig_size, &pkt);
1909 if (!NT_STATUS_IS_OK(req->status)) {
1910 req->state = RPC_REQUEST_DONE;
1911 DLIST_REMOVE(p->conn->pending, req);
1915 if (last_frag && !need_async) {
1919 req->status = dcerpc_send_request(p->conn, &blob, do_trans);
1920 if (!NT_STATUS_IS_OK(req->status)) {
1921 req->state = RPC_REQUEST_DONE;
1922 DLIST_REMOVE(p->conn->pending, req);
1926 if (last_frag && !do_trans) {
1927 req->status = dcerpc_send_read(p->conn);
1928 if (!NT_STATUS_IS_OK(req->status)) {
1929 req->state = RPC_REQUEST_DONE;
1930 DLIST_REMOVE(p->conn->pending, req);
1939 static void dcerpc_io_trigger(struct tevent_context *ctx,
1940 struct tevent_immediate *im,
1943 struct dcecli_connection *c =
1944 talloc_get_type_abort(private_data,
1945 struct dcecli_connection);
1947 c->io_trigger_pending = false;
1949 dcerpc_schedule_io_trigger(c);
1951 dcerpc_ship_next_request(c);
1954 static void dcerpc_schedule_io_trigger(struct dcecli_connection *c)
1960 if (c->request_queue == NULL) {
1964 if (c->request_queue->wait_for_sync && c->pending) {
1968 if (c->io_trigger_pending) {
1972 c->io_trigger_pending = true;
1974 tevent_schedule_immediate(c->io_trigger,
1981 perform the receive side of a async dcerpc request
1983 static NTSTATUS dcerpc_request_recv(struct rpc_request *req,
1984 TALLOC_CTX *mem_ctx,
1985 DATA_BLOB *stub_data)
1989 while (req->state != RPC_REQUEST_DONE) {
1990 struct tevent_context *ctx = req->p->conn->event_ctx;
1991 if (tevent_loop_once(ctx) != 0) {
1992 return NT_STATUS_CONNECTION_DISCONNECTED;
1995 *stub_data = req->payload;
1996 status = req->status;
1997 if (stub_data->data) {
1998 stub_data->data = talloc_steal(mem_ctx, stub_data->data);
2000 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
2001 req->p->last_fault_code = req->fault_code;
2003 talloc_unlink(talloc_parent(req), req);
2008 this is a paranoid NDR validator. For every packet we push onto the wire
2009 we pull it back again, then push it again. Then we compare the raw NDR data
2010 for that to the NDR we initially generated. If they don't match then we know
2011 we must have a bug in either the pull or push side of our code
2013 static NTSTATUS dcerpc_ndr_validate_in(struct dcecli_connection *c,
2014 TALLOC_CTX *mem_ctx,
2017 ndr_push_flags_fn_t ndr_push,
2018 ndr_pull_flags_fn_t ndr_pull)
2021 struct ndr_pull *pull;
2022 struct ndr_push *push;
2024 enum ndr_err_code ndr_err;
2026 st = talloc_size(mem_ctx, struct_size);
2028 return NT_STATUS_NO_MEMORY;
2031 pull = ndr_pull_init_flags(c, &blob, mem_ctx);
2033 return NT_STATUS_NO_MEMORY;
2035 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
2037 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
2038 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
2041 if (c->flags & DCERPC_NDR64) {
2042 pull->flags |= LIBNDR_FLAG_NDR64;
2045 ndr_err = ndr_pull(pull, NDR_IN, st);
2046 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2047 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2048 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
2049 "failed input validation pull - %s",
2051 return ndr_map_error2ntstatus(ndr_err);
2054 push = ndr_push_init_ctx(mem_ctx);
2056 return NT_STATUS_NO_MEMORY;
2059 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
2060 push->flags |= LIBNDR_FLAG_BIGENDIAN;
2063 if (c->flags & DCERPC_NDR64) {
2064 push->flags |= LIBNDR_FLAG_NDR64;
2067 ndr_err = ndr_push(push, NDR_IN, st);
2068 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2069 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2070 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
2071 "failed input validation push - %s",
2073 return ndr_map_error2ntstatus(ndr_err);
2076 blob2 = ndr_push_blob(push);
2078 if (data_blob_cmp(&blob, &blob2) != 0) {
2079 DEBUG(3,("original:\n"));
2080 dump_data(3, blob.data, blob.length);
2081 DEBUG(3,("secondary:\n"));
2082 dump_data(3, blob2.data, blob2.length);
2083 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
2084 "failed input validation blobs doesn't match");
2085 return ndr_map_error2ntstatus(ndr_err);
2088 return NT_STATUS_OK;
2092 this is a paranoid NDR input validator. For every packet we pull
2093 from the wire we push it back again then pull and push it
2094 again. Then we compare the raw NDR data for that to the NDR we
2095 initially generated. If they don't match then we know we must have a
2096 bug in either the pull or push side of our code
2098 static NTSTATUS dcerpc_ndr_validate_out(struct dcecli_connection *c,
2099 struct ndr_pull *pull_in,
2102 ndr_push_flags_fn_t ndr_push,
2103 ndr_pull_flags_fn_t ndr_pull,
2104 ndr_print_function_t ndr_print)
2107 struct ndr_pull *pull;
2108 struct ndr_push *push;
2109 DATA_BLOB blob, blob2;
2110 TALLOC_CTX *mem_ctx = pull_in;
2112 enum ndr_err_code ndr_err;
2114 st = talloc_size(mem_ctx, struct_size);
2116 return NT_STATUS_NO_MEMORY;
2118 memcpy(st, struct_ptr, struct_size);
2120 push = ndr_push_init_ctx(mem_ctx);
2122 return NT_STATUS_NO_MEMORY;
2125 ndr_err = ndr_push(push, NDR_OUT, struct_ptr);
2126 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2127 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2128 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2129 "failed output validation push - %s",
2131 return ndr_map_error2ntstatus(ndr_err);
2134 blob = ndr_push_blob(push);
2136 pull = ndr_pull_init_flags(c, &blob, mem_ctx);
2138 return NT_STATUS_NO_MEMORY;
2141 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
2142 ndr_err = ndr_pull(pull, NDR_OUT, st);
2143 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2144 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2145 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
2146 "failed output validation pull - %s",
2148 return ndr_map_error2ntstatus(ndr_err);
2151 push = ndr_push_init_ctx(mem_ctx);
2153 return NT_STATUS_NO_MEMORY;
2156 ndr_err = ndr_push(push, NDR_OUT, st);
2157 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2158 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2159 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2160 "failed output validation push2 - %s",
2162 return ndr_map_error2ntstatus(ndr_err);
2165 blob2 = ndr_push_blob(push);
2167 if (data_blob_cmp(&blob, &blob2) != 0) {
2168 DEBUG(3,("original:\n"));
2169 dump_data(3, blob.data, blob.length);
2170 DEBUG(3,("secondary:\n"));
2171 dump_data(3, blob2.data, blob2.length);
2172 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2173 "failed output validation blobs doesn't match");
2174 return ndr_map_error2ntstatus(ndr_err);
2177 /* this checks the printed forms of the two structures, which effectively
2178 tests all of the value() attributes */
2179 s1 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE",
2180 NDR_OUT, struct_ptr);
2181 s2 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE",
2183 if (strcmp(s1, s2) != 0) {
2185 DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1, s2));
2187 /* this is sometimes useful */
2188 printf("VALIDATE ERROR\n");
2189 file_save("wire.dat", s1, strlen(s1));
2190 file_save("gen.dat", s2, strlen(s2));
2191 system("diff -u wire.dat gen.dat");
2193 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
2194 "failed output validation strings doesn't match");
2195 return ndr_map_error2ntstatus(ndr_err);
2198 return NT_STATUS_OK;
2202 a useful function for retrieving the server name we connected to
2204 _PUBLIC_ const char *dcerpc_server_name(struct dcerpc_pipe *p)
2206 return p->conn ? p->conn->server_name : NULL;
2211 get the dcerpc auth_level for a open connection
2213 uint32_t dcerpc_auth_level(struct dcecli_connection *c)
2217 if (c->flags & DCERPC_SEAL) {
2218 auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
2219 } else if (c->flags & DCERPC_SIGN) {
2220 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
2221 } else if (c->flags & DCERPC_CONNECT) {
2222 auth_level = DCERPC_AUTH_LEVEL_CONNECT;
2224 auth_level = DCERPC_AUTH_LEVEL_NONE;
2229 struct dcerpc_alter_context_state {
2230 struct tevent_context *ev;
2231 struct dcerpc_pipe *p;
2234 static void dcerpc_alter_context_fail_handler(struct rpc_request *subreq);
2235 static void dcerpc_alter_context_recv_handler(struct rpc_request *req,
2236 DATA_BLOB *raw_packet,
2237 struct ncacn_packet *pkt);
2239 struct tevent_req *dcerpc_alter_context_send(TALLOC_CTX *mem_ctx,
2240 struct tevent_context *ev,
2241 struct dcerpc_pipe *p,
2242 const struct ndr_syntax_id *syntax,
2243 const struct ndr_syntax_id *transfer_syntax)
2245 struct tevent_req *req;
2246 struct dcerpc_alter_context_state *state;
2247 struct ncacn_packet pkt;
2250 struct rpc_request *subreq;
2253 req = tevent_req_create(mem_ctx, &state,
2254 struct dcerpc_alter_context_state);
2262 p->syntax = *syntax;
2263 p->transfer_syntax = *transfer_syntax;
2265 flags = dcerpc_binding_get_flags(p->binding);
2267 init_ncacn_hdr(p->conn, &pkt);
2269 pkt.ptype = DCERPC_PKT_ALTER;
2270 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
2271 pkt.call_id = p->conn->call_id;
2272 pkt.auth_length = 0;
2274 if (flags & DCERPC_CONCURRENT_MULTIPLEX) {
2275 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
2278 pkt.u.alter.max_xmit_frag = p->conn->srv_max_xmit_frag;
2279 pkt.u.alter.max_recv_frag = p->conn->srv_max_recv_frag;
2280 pkt.u.alter.assoc_group_id = dcerpc_binding_get_assoc_group_id(p->binding);
2281 pkt.u.alter.num_contexts = 1;
2282 pkt.u.alter.ctx_list = talloc_array(state, struct dcerpc_ctx_list, 1);
2283 if (tevent_req_nomem(pkt.u.alter.ctx_list, req)) {
2284 return tevent_req_post(req, ev);
2286 pkt.u.alter.ctx_list[0].context_id = p->context_id;
2287 pkt.u.alter.ctx_list[0].num_transfer_syntaxes = 1;
2288 pkt.u.alter.ctx_list[0].abstract_syntax = p->syntax;
2289 pkt.u.alter.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
2290 pkt.u.alter.auth_info = data_blob(NULL, 0);
2292 /* construct the NDR form of the packet */
2293 status = ncacn_push_auth(&blob, state, &pkt,
2294 p->conn->security_state.tmp_auth_info.out);
2295 if (tevent_req_nterror(req, status)) {
2296 return tevent_req_post(req, ev);
2300 * we allocate a dcerpc_request so we can be in the same
2301 * request queue as normal requests
2303 subreq = talloc_zero(state, struct rpc_request);
2304 if (tevent_req_nomem(subreq, req)) {
2305 return tevent_req_post(req, ev);
2308 subreq->state = RPC_REQUEST_PENDING;
2309 subreq->call_id = pkt.call_id;
2310 subreq->async.private_data = req;
2311 subreq->async.callback = dcerpc_alter_context_fail_handler;
2313 subreq->recv_handler = dcerpc_alter_context_recv_handler;
2314 DLIST_ADD_END(p->conn->pending, subreq, struct rpc_request *);
2315 talloc_set_destructor(subreq, dcerpc_req_dequeue);
2317 status = dcerpc_send_request(p->conn, &blob, true);
2318 if (tevent_req_nterror(req, status)) {
2319 return tevent_req_post(req, ev);
2322 tevent_add_timer(ev, subreq,
2323 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
2324 dcerpc_timeout_handler, subreq);
2329 static void dcerpc_alter_context_fail_handler(struct rpc_request *subreq)
2331 struct tevent_req *req =
2332 talloc_get_type_abort(subreq->async.private_data,
2334 struct dcerpc_alter_context_state *state =
2335 tevent_req_data(req,
2336 struct dcerpc_alter_context_state);
2337 NTSTATUS status = subreq->status;
2339 TALLOC_FREE(subreq);
2342 * We trigger the callback in the next event run
2343 * because the code in this file might trigger
2344 * multiple request callbacks from within a single
2347 * In order to avoid segfaults from within
2348 * dcerpc_connection_dead() we call
2349 * tevent_req_defer_callback().
2351 tevent_req_defer_callback(req, state->ev);
2353 tevent_req_nterror(req, status);
2356 static void dcerpc_alter_context_recv_handler(struct rpc_request *subreq,
2357 DATA_BLOB *raw_packet,
2358 struct ncacn_packet *pkt)
2360 struct tevent_req *req =
2361 talloc_get_type_abort(subreq->async.private_data,
2363 struct dcerpc_alter_context_state *state =
2364 tevent_req_data(req,
2365 struct dcerpc_alter_context_state);
2366 struct dcecli_connection *conn = state->p->conn;
2367 struct dcecli_security *sec = &conn->security_state;
2371 * Note that pkt is allocated under raw_packet->data,
2372 * while raw_packet->data is a child of subreq.
2374 talloc_steal(state, raw_packet->data);
2375 TALLOC_FREE(subreq);
2378 * We trigger the callback in the next event run
2379 * because the code in this file might trigger
2380 * multiple request callbacks from within a single
2383 * In order to avoid segfaults from within
2384 * dcerpc_connection_dead() we call
2385 * tevent_req_defer_callback().
2387 tevent_req_defer_callback(req, state->ev);
2389 if (pkt->ptype == DCERPC_PKT_FAULT) {
2390 DEBUG(5,("dcerpc: alter_resp - rpc fault: %s\n",
2391 dcerpc_errstr(state, pkt->u.fault.status)));
2392 if (pkt->u.fault.status == DCERPC_FAULT_ACCESS_DENIED) {
2393 state->p->last_fault_code = pkt->u.fault.status;
2394 tevent_req_nterror(req, NT_STATUS_LOGON_FAILURE);
2395 } else if (pkt->u.fault.status == DCERPC_FAULT_SEC_PKG_ERROR) {
2396 state->p->last_fault_code = pkt->u.fault.status;
2397 tevent_req_nterror(req, NT_STATUS_LOGON_FAILURE);
2399 state->p->last_fault_code = pkt->u.fault.status;
2400 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
2401 tevent_req_nterror(req, status);
2406 status = dcerpc_verify_ncacn_packet_header(pkt,
2407 DCERPC_PKT_ALTER_RESP,
2408 pkt->u.alter_resp.auth_info.length,
2409 DCERPC_PFC_FLAG_FIRST |
2410 DCERPC_PFC_FLAG_LAST,
2411 DCERPC_PFC_FLAG_CONC_MPX |
2412 DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN);
2413 if (!NT_STATUS_IS_OK(status)) {
2414 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
2415 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
2419 if (pkt->u.alter_resp.num_results != 1) {
2420 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
2421 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
2425 if (pkt->u.alter_resp.ctx_list[0].result != 0) {
2426 status = dcerpc_map_ack_reason(&pkt->u.alter_resp.ctx_list[0]);
2427 DEBUG(2,("dcerpc: alter_resp failed - reason %d - %s\n",
2428 pkt->u.alter_resp.ctx_list[0].reason.value,
2429 nt_errstr(status)));
2430 tevent_req_nterror(req, status);
2434 /* the alter_resp might contain a reply set of credentials */
2435 if (pkt->auth_length != 0 && sec->tmp_auth_info.in != NULL) {
2436 uint32_t auth_length;
2438 status = dcerpc_pull_auth_trailer(pkt, sec->tmp_auth_info.mem,
2439 &pkt->u.alter_resp.auth_info,
2440 sec->tmp_auth_info.in,
2441 &auth_length, true);
2442 if (tevent_req_nterror(req, status)) {
2447 tevent_req_done(req);
2450 NTSTATUS dcerpc_alter_context_recv(struct tevent_req *req)
2452 return tevent_req_simple_recv_ntstatus(req);
2456 send a dcerpc alter_context request
2458 _PUBLIC_ NTSTATUS dcerpc_alter_context(struct dcerpc_pipe *p,
2459 TALLOC_CTX *mem_ctx,
2460 const struct ndr_syntax_id *syntax,
2461 const struct ndr_syntax_id *transfer_syntax)
2463 struct tevent_req *subreq;
2464 struct tevent_context *ev = p->conn->event_ctx;
2467 /* TODO: create a new event context here */
2469 subreq = dcerpc_alter_context_send(mem_ctx, ev,
2470 p, syntax, transfer_syntax);
2471 if (subreq == NULL) {
2472 return NT_STATUS_NO_MEMORY;
2475 ok = tevent_req_poll(subreq, ev);
2478 status = map_nt_error_from_unix_common(errno);
2482 return dcerpc_alter_context_recv(subreq);
2485 static void dcerpc_transport_dead(struct dcecli_connection *c, NTSTATUS status)
2487 if (c->transport.stream == NULL) {
2491 tevent_queue_stop(c->transport.write_queue);
2492 TALLOC_FREE(c->transport.read_subreq);
2493 TALLOC_FREE(c->transport.stream);
2495 if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) {
2496 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
2499 if (NT_STATUS_EQUAL(NT_STATUS_OK, status)) {
2500 status = NT_STATUS_END_OF_FILE;
2503 dcerpc_recv_data(c, NULL, status);
2508 shutdown SMB pipe connection
2510 struct dcerpc_shutdown_pipe_state {
2511 struct dcecli_connection *c;
2515 static void dcerpc_shutdown_pipe_done(struct tevent_req *subreq);
2517 static NTSTATUS dcerpc_shutdown_pipe(struct dcecli_connection *c, NTSTATUS status)
2519 struct dcerpc_shutdown_pipe_state *state;
2520 struct tevent_req *subreq;
2522 if (c->transport.stream == NULL) {
2523 return NT_STATUS_OK;
2526 state = talloc_zero(c, struct dcerpc_shutdown_pipe_state);
2527 if (state == NULL) {
2528 return NT_STATUS_NO_MEMORY;
2531 state->status = status;
2533 subreq = tstream_disconnect_send(state, c->event_ctx, c->transport.stream);
2534 if (subreq == NULL) {
2535 return NT_STATUS_NO_MEMORY;
2537 tevent_req_set_callback(subreq, dcerpc_shutdown_pipe_done, state);
2542 static void dcerpc_shutdown_pipe_done(struct tevent_req *subreq)
2544 struct dcerpc_shutdown_pipe_state *state =
2545 tevent_req_callback_data(subreq, struct dcerpc_shutdown_pipe_state);
2546 struct dcecli_connection *c = state->c;
2547 NTSTATUS status = state->status;
2551 * here we ignore the return values...
2553 tstream_disconnect_recv(subreq, &error);
2554 TALLOC_FREE(subreq);
2558 dcerpc_transport_dead(c, status);
2563 struct dcerpc_send_read_state {
2564 struct dcecli_connection *p;
2567 static int dcerpc_send_read_state_destructor(struct dcerpc_send_read_state *state)
2569 struct dcecli_connection *p = state->p;
2571 p->transport.read_subreq = NULL;
2576 static void dcerpc_send_read_done(struct tevent_req *subreq);
2578 static NTSTATUS dcerpc_send_read(struct dcecli_connection *p)
2580 struct dcerpc_send_read_state *state;
2582 if (p->transport.read_subreq != NULL) {
2583 p->transport.pending_reads++;
2584 return NT_STATUS_OK;
2587 state = talloc_zero(p, struct dcerpc_send_read_state);
2588 if (state == NULL) {
2589 return NT_STATUS_NO_MEMORY;
2593 talloc_set_destructor(state, dcerpc_send_read_state_destructor);
2595 p->transport.read_subreq = dcerpc_read_ncacn_packet_send(state,
2597 p->transport.stream);
2598 if (p->transport.read_subreq == NULL) {
2599 return NT_STATUS_NO_MEMORY;
2601 tevent_req_set_callback(p->transport.read_subreq, dcerpc_send_read_done, state);
2603 return NT_STATUS_OK;
2606 static void dcerpc_send_read_done(struct tevent_req *subreq)
2608 struct dcerpc_send_read_state *state =
2609 tevent_req_callback_data(subreq,
2610 struct dcerpc_send_read_state);
2611 struct dcecli_connection *p = state->p;
2613 struct ncacn_packet *pkt;
2616 status = dcerpc_read_ncacn_packet_recv(subreq, state,
2618 TALLOC_FREE(subreq);
2619 if (!NT_STATUS_IS_OK(status)) {
2621 dcerpc_transport_dead(p, status);
2626 * here we steal into thet connection context,
2627 * but p->transport.recv_data() will steal or free it again
2629 talloc_steal(p, blob.data);
2632 if (p->transport.pending_reads > 0) {
2633 p->transport.pending_reads--;
2635 status = dcerpc_send_read(p);
2636 if (!NT_STATUS_IS_OK(status)) {
2637 dcerpc_transport_dead(p, status);
2642 dcerpc_recv_data(p, &blob, NT_STATUS_OK);
2645 struct dcerpc_send_request_state {
2646 struct dcecli_connection *p;
2651 static int dcerpc_send_request_state_destructor(struct dcerpc_send_request_state *state)
2653 struct dcecli_connection *p = state->p;
2655 p->transport.read_subreq = NULL;
2660 static void dcerpc_send_request_wait_done(struct tevent_req *subreq);
2661 static void dcerpc_send_request_done(struct tevent_req *subreq);
2663 static NTSTATUS dcerpc_send_request(struct dcecli_connection *p, DATA_BLOB *data,
2666 struct dcerpc_send_request_state *state;
2667 struct tevent_req *subreq;
2668 bool use_trans = trigger_read;
2670 if (p->transport.stream == NULL) {
2671 return NT_STATUS_CONNECTION_DISCONNECTED;
2674 state = talloc_zero(p, struct dcerpc_send_request_state);
2675 if (state == NULL) {
2676 return NT_STATUS_NO_MEMORY;
2680 state->blob = data_blob_talloc(state, data->data, data->length);
2681 if (state->blob.data == NULL) {
2683 return NT_STATUS_NO_MEMORY;
2685 state->iov.iov_base = (void *)state->blob.data;
2686 state->iov.iov_len = state->blob.length;
2688 if (p->transport.read_subreq != NULL) {
2692 if (!tstream_is_smbXcli_np(p->transport.stream)) {
2698 * we need to block reads until our write is
2699 * the next in the write queue.
2701 p->transport.read_subreq = tevent_queue_wait_send(state, p->event_ctx,
2702 p->transport.write_queue);
2703 if (p->transport.read_subreq == NULL) {
2705 return NT_STATUS_NO_MEMORY;
2707 tevent_req_set_callback(p->transport.read_subreq,
2708 dcerpc_send_request_wait_done,
2711 talloc_set_destructor(state, dcerpc_send_request_state_destructor);
2713 trigger_read = false;
2716 subreq = tstream_writev_queue_send(state, p->event_ctx,
2717 p->transport.stream,
2718 p->transport.write_queue,
2720 if (subreq == NULL) {
2722 return NT_STATUS_NO_MEMORY;
2724 tevent_req_set_callback(subreq, dcerpc_send_request_done, state);
2727 dcerpc_send_read(p);
2730 return NT_STATUS_OK;
2733 static void dcerpc_send_request_wait_done(struct tevent_req *subreq)
2735 struct dcerpc_send_request_state *state =
2736 tevent_req_callback_data(subreq,
2737 struct dcerpc_send_request_state);
2738 struct dcecli_connection *p = state->p;
2742 p->transport.read_subreq = NULL;
2743 talloc_set_destructor(state, NULL);
2745 ok = tevent_queue_wait_recv(subreq);
2748 dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2752 if (tevent_queue_length(p->transport.write_queue) <= 2) {
2753 status = tstream_smbXcli_np_use_trans(p->transport.stream);
2754 if (!NT_STATUS_IS_OK(status)) {
2756 dcerpc_transport_dead(p, status);
2761 /* we free subreq after tstream_cli_np_use_trans */
2762 TALLOC_FREE(subreq);
2764 dcerpc_send_read(p);
2767 static void dcerpc_send_request_done(struct tevent_req *subreq)
2769 struct dcerpc_send_request_state *state =
2770 tevent_req_callback_data(subreq,
2771 struct dcerpc_send_request_state);
2775 ret = tstream_writev_queue_recv(subreq, &error);
2776 TALLOC_FREE(subreq);
2778 struct dcecli_connection *p = state->p;
2779 NTSTATUS status = map_nt_error_from_unix_common(error);
2782 dcerpc_transport_dead(p, status);