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 "../lib/util/dlinklist.h"
25 #include "lib/events/events.h"
26 #include "librpc/rpc/dcerpc.h"
27 #include "librpc/rpc/dcerpc_proto.h"
28 #include "librpc/gen_ndr/ndr_misc.h"
29 #include "librpc/gen_ndr/ndr_dcerpc.h"
30 #include "libcli/composite/composite.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"
36 enum rpc_request_state {
43 handle for an async dcerpc request
46 struct rpc_request *next, *prev;
47 struct dcerpc_pipe *p;
50 enum rpc_request_state state;
55 /* this is used to distinguish bind and alter_context requests
56 from normal requests */
57 void (*recv_handler)(struct rpc_request *conn,
58 DATA_BLOB *blob, struct ncacn_packet *pkt);
60 const struct GUID *object;
62 DATA_BLOB request_data;
65 /* use by the ndr level async recv call */
67 const struct ndr_interface_table *table;
74 void (*callback)(struct rpc_request *);
79 _PUBLIC_ NTSTATUS dcerpc_init(void)
84 static void dcerpc_connection_dead(struct dcecli_connection *conn, NTSTATUS status);
85 static void dcerpc_schedule_io_trigger(struct dcecli_connection *c);
87 static struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p,
88 const struct GUID *object,
90 DATA_BLOB *stub_data);
91 static NTSTATUS dcerpc_request_recv(struct rpc_request *req,
93 DATA_BLOB *stub_data);
94 static NTSTATUS dcerpc_ndr_validate_in(struct dcecli_connection *c,
98 ndr_push_flags_fn_t ndr_push,
99 ndr_pull_flags_fn_t ndr_pull);
100 static NTSTATUS dcerpc_ndr_validate_out(struct dcecli_connection *c,
101 struct ndr_pull *pull_in,
104 ndr_push_flags_fn_t ndr_push,
105 ndr_pull_flags_fn_t ndr_pull,
106 ndr_print_function_t ndr_print);
108 /* destroy a dcerpc connection */
109 static int dcerpc_connection_destructor(struct dcecli_connection *conn)
112 conn->free_skipped = true;
115 dcerpc_connection_dead(conn, NT_STATUS_LOCAL_DISCONNECT);
120 /* initialise a dcerpc connection.
121 the event context is optional
123 static struct dcecli_connection *dcerpc_connection_init(TALLOC_CTX *mem_ctx,
124 struct tevent_context *ev)
126 struct dcecli_connection *c;
128 c = talloc_zero(mem_ctx, struct dcecli_connection);
135 if (c->event_ctx == NULL) {
141 c->security_state.auth_info = NULL;
142 c->security_state.session_key = dcerpc_generic_session_key;
143 c->security_state.generic_state = NULL;
144 c->binding_string = NULL;
146 c->srv_max_xmit_frag = 0;
147 c->srv_max_recv_frag = 0;
150 c->io_trigger = tevent_create_immediate(c);
151 if (c->io_trigger == NULL) {
156 talloc_set_destructor(c, dcerpc_connection_destructor);
161 struct dcerpc_bh_state {
162 struct dcerpc_pipe *p;
165 static bool dcerpc_bh_is_connected(struct dcerpc_binding_handle *h)
167 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
168 struct dcerpc_bh_state);
178 if (hs->p->conn->dead) {
185 static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle *h,
188 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
189 struct dcerpc_bh_state);
193 return DCERPC_REQUEST_TIMEOUT;
196 old = hs->p->request_timeout;
197 hs->p->request_timeout = timeout;
202 struct dcerpc_bh_raw_call_state {
203 struct tevent_context *ev;
204 struct dcerpc_binding_handle *h;
210 static void dcerpc_bh_raw_call_done(struct rpc_request *subreq);
212 static struct tevent_req *dcerpc_bh_raw_call_send(TALLOC_CTX *mem_ctx,
213 struct tevent_context *ev,
214 struct dcerpc_binding_handle *h,
215 const struct GUID *object,
218 const uint8_t *in_data,
221 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
222 struct dcerpc_bh_state);
223 struct tevent_req *req;
224 struct dcerpc_bh_raw_call_state *state;
226 struct rpc_request *subreq;
228 req = tevent_req_create(mem_ctx, &state,
229 struct dcerpc_bh_raw_call_state);
235 state->in_data.data = discard_const_p(uint8_t, in_data);
236 state->in_data.length = in_length;
238 ok = dcerpc_bh_is_connected(h);
240 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
241 return tevent_req_post(req, ev);
244 subreq = dcerpc_request_send(hs->p,
248 if (tevent_req_nomem(subreq, req)) {
249 return tevent_req_post(req, ev);
251 subreq->async.callback = dcerpc_bh_raw_call_done;
252 subreq->async.private_data = req;
257 static void dcerpc_bh_raw_call_done(struct rpc_request *subreq)
259 struct tevent_req *req =
260 talloc_get_type_abort(subreq->async.private_data,
262 struct dcerpc_bh_raw_call_state *state =
264 struct dcerpc_bh_raw_call_state);
268 state->out_flags = 0;
269 if (subreq->flags & DCERPC_PULL_BIGENDIAN) {
270 state->out_flags |= LIBNDR_FLAG_BIGENDIAN;
273 fault_code = subreq->fault_code;
275 status = dcerpc_request_recv(subreq, state, &state->out_data);
276 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
277 status = dcerpc_fault_to_nt_status(fault_code);
281 * We trigger the callback in the next event run
282 * because the code in this file might trigger
283 * multiple request callbacks from within a single
286 * In order to avoid segfaults from within
287 * dcerpc_connection_dead() we call
288 * tevent_req_defer_callback().
290 tevent_req_defer_callback(req, state->ev);
292 if (!NT_STATUS_IS_OK(status)) {
293 tevent_req_nterror(req, status);
297 tevent_req_done(req);
300 static NTSTATUS dcerpc_bh_raw_call_recv(struct tevent_req *req,
306 struct dcerpc_bh_raw_call_state *state =
308 struct dcerpc_bh_raw_call_state);
311 if (tevent_req_is_nterror(req, &status)) {
312 tevent_req_received(req);
316 *out_data = talloc_move(mem_ctx, &state->out_data.data);
317 *out_length = state->out_data.length;
318 *out_flags = state->out_flags;
319 tevent_req_received(req);
323 struct dcerpc_bh_disconnect_state {
327 static struct tevent_req *dcerpc_bh_disconnect_send(TALLOC_CTX *mem_ctx,
328 struct tevent_context *ev,
329 struct dcerpc_binding_handle *h)
331 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
332 struct dcerpc_bh_state);
333 struct tevent_req *req;
334 struct dcerpc_bh_disconnect_state *state;
337 req = tevent_req_create(mem_ctx, &state,
338 struct dcerpc_bh_disconnect_state);
343 ok = dcerpc_bh_is_connected(h);
345 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
346 return tevent_req_post(req, ev);
349 /* TODO: do a real disconnect ... */
352 tevent_req_done(req);
353 return tevent_req_post(req, ev);
356 static NTSTATUS dcerpc_bh_disconnect_recv(struct tevent_req *req)
360 if (tevent_req_is_nterror(req, &status)) {
361 tevent_req_received(req);
365 tevent_req_received(req);
369 static bool dcerpc_bh_push_bigendian(struct dcerpc_binding_handle *h)
371 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
372 struct dcerpc_bh_state);
374 if (hs->p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
381 static bool dcerpc_bh_ref_alloc(struct dcerpc_binding_handle *h)
383 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
384 struct dcerpc_bh_state);
386 if (hs->p->conn->flags & DCERPC_NDR_REF_ALLOC) {
393 static bool dcerpc_bh_use_ndr64(struct dcerpc_binding_handle *h)
395 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
396 struct dcerpc_bh_state);
398 if (hs->p->conn->flags & DCERPC_NDR64) {
405 static void dcerpc_bh_do_ndr_print(struct dcerpc_binding_handle *h,
407 const void *_struct_ptr,
408 const struct ndr_interface_call *call)
410 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
411 struct dcerpc_bh_state);
412 void *struct_ptr = discard_const(_struct_ptr);
414 if (ndr_flags & NDR_IN) {
415 if (hs->p->conn->flags & DCERPC_DEBUG_PRINT_IN) {
416 ndr_print_function_debug(call->ndr_print,
422 if (ndr_flags & NDR_OUT) {
423 if (hs->p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
424 ndr_print_function_debug(call->ndr_print,
432 static void dcerpc_bh_ndr_push_failed(struct dcerpc_binding_handle *h,
434 const void *struct_ptr,
435 const struct ndr_interface_call *call)
437 DEBUG(2,("Unable to ndr_push structure for %s - %s\n",
438 call->name, nt_errstr(error)));
441 static void dcerpc_bh_ndr_pull_failed(struct dcerpc_binding_handle *h,
443 const DATA_BLOB *blob,
444 const struct ndr_interface_call *call)
446 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
447 struct dcerpc_bh_state);
448 const uint32_t num_examples = 20;
451 DEBUG(2,("Unable to ndr_pull structure for %s - %s\n",
452 call->name, nt_errstr(error)));
454 if (hs->p->conn->packet_log_dir == NULL) return;
456 for (i=0;i<num_examples;i++) {
458 asprintf(&name, "%s/rpclog/%s-out.%d",
459 hs->p->conn->packet_log_dir,
464 if (!file_exist(name)) {
465 if (file_save(name, blob->data, blob->length)) {
466 DEBUG(10,("Logged rpc packet to %s\n", name));
475 static NTSTATUS dcerpc_bh_ndr_validate_in(struct dcerpc_binding_handle *h,
477 const DATA_BLOB *blob,
478 const struct ndr_interface_call *call)
480 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
481 struct dcerpc_bh_state);
483 if (hs->p->conn->flags & DCERPC_DEBUG_VALIDATE_IN) {
486 status = dcerpc_ndr_validate_in(hs->p->conn,
492 if (!NT_STATUS_IS_OK(status)) {
493 DEBUG(0,("Validation [in] failed for %s - %s\n",
494 call->name, nt_errstr(status)));
499 DEBUG(10,("rpc request data:\n"));
500 dump_data(10, blob->data, blob->length);
505 static NTSTATUS dcerpc_bh_ndr_validate_out(struct dcerpc_binding_handle *h,
506 struct ndr_pull *pull_in,
507 const void *_struct_ptr,
508 const struct ndr_interface_call *call)
510 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
511 struct dcerpc_bh_state);
512 void *struct_ptr = discard_const(_struct_ptr);
514 DEBUG(10,("rpc reply data:\n"));
515 dump_data(10, pull_in->data, pull_in->data_size);
517 if (pull_in->offset != pull_in->data_size) {
518 DEBUG(0,("Warning! ignoring %u unread bytes at ofs:%u (0x%08X) for %s!\n",
519 pull_in->data_size - pull_in->offset,
520 pull_in->offset, pull_in->offset,
522 /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here,
523 but it turns out that early versions of NT
524 (specifically NT3.1) add junk onto the end of rpc
525 packets, so if we want to interoperate at all with
526 those versions then we need to ignore this error */
529 if (hs->p->conn->flags & DCERPC_DEBUG_VALIDATE_OUT) {
532 status = dcerpc_ndr_validate_out(hs->p->conn,
539 if (!NT_STATUS_IS_OK(status)) {
540 DEBUG(2,("Validation [out] failed for %s - %s\n",
541 call->name, nt_errstr(status)));
549 static const struct dcerpc_binding_handle_ops dcerpc_bh_ops = {
551 .is_connected = dcerpc_bh_is_connected,
552 .set_timeout = dcerpc_bh_set_timeout,
553 .raw_call_send = dcerpc_bh_raw_call_send,
554 .raw_call_recv = dcerpc_bh_raw_call_recv,
555 .disconnect_send = dcerpc_bh_disconnect_send,
556 .disconnect_recv = dcerpc_bh_disconnect_recv,
558 .push_bigendian = dcerpc_bh_push_bigendian,
559 .ref_alloc = dcerpc_bh_ref_alloc,
560 .use_ndr64 = dcerpc_bh_use_ndr64,
561 .do_ndr_print = dcerpc_bh_do_ndr_print,
562 .ndr_push_failed = dcerpc_bh_ndr_push_failed,
563 .ndr_pull_failed = dcerpc_bh_ndr_pull_failed,
564 .ndr_validate_in = dcerpc_bh_ndr_validate_in,
565 .ndr_validate_out = dcerpc_bh_ndr_validate_out,
568 /* initialise a dcerpc pipe. */
569 struct dcerpc_binding_handle *dcerpc_pipe_binding_handle(struct dcerpc_pipe *p)
571 struct dcerpc_binding_handle *h;
572 struct dcerpc_bh_state *hs;
574 h = dcerpc_binding_handle_create(p,
579 struct dcerpc_bh_state,
586 dcerpc_binding_handle_set_sync_ev(h, p->conn->event_ctx);
591 /* initialise a dcerpc pipe. */
592 _PUBLIC_ struct dcerpc_pipe *dcerpc_pipe_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev)
594 struct dcerpc_pipe *p;
596 p = talloc_zero(mem_ctx, struct dcerpc_pipe);
601 p->conn = dcerpc_connection_init(p, ev);
602 if (p->conn == NULL) {
607 p->last_fault_code = 0;
609 p->request_timeout = DCERPC_REQUEST_TIMEOUT;
612 ZERO_STRUCT(p->syntax);
613 ZERO_STRUCT(p->transfer_syntax);
616 p->conn->flags |= DCERPC_DEBUG_PRINT_BOTH;
619 p->binding_handle = dcerpc_pipe_binding_handle(p);
620 if (p->binding_handle == NULL) {
630 choose the next call id to use
632 static uint32_t next_call_id(struct dcecli_connection *c)
635 if (c->call_id == 0) {
642 setup for a ndr pull, also setting up any flags from the binding string
644 static struct ndr_pull *ndr_pull_init_flags(struct dcecli_connection *c,
645 DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
647 struct ndr_pull *ndr = ndr_pull_init_blob(blob, mem_ctx);
649 if (ndr == NULL) return ndr;
651 if (c->flags & DCERPC_DEBUG_PAD_CHECK) {
652 ndr->flags |= LIBNDR_FLAG_PAD_CHECK;
655 if (c->flags & DCERPC_NDR_REF_ALLOC) {
656 ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
659 if (c->flags & DCERPC_NDR64) {
660 ndr->flags |= LIBNDR_FLAG_NDR64;
667 parse a data blob into a ncacn_packet structure. This handles both
668 input and output packets
670 static NTSTATUS ncacn_pull(struct dcecli_connection *c, DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
671 struct ncacn_packet *pkt)
673 struct ndr_pull *ndr;
674 enum ndr_err_code ndr_err;
676 ndr = ndr_pull_init_flags(c, blob, mem_ctx);
678 return NT_STATUS_NO_MEMORY;
681 if (! (CVAL(blob->data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) {
682 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
685 ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
686 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
687 return ndr_map_error2ntstatus(ndr_err);
694 parse the authentication information on a dcerpc response packet
696 static NTSTATUS ncacn_pull_request_auth(struct dcecli_connection *c, TALLOC_CTX *mem_ctx,
697 DATA_BLOB *raw_packet,
698 struct ncacn_packet *pkt)
701 struct dcerpc_auth auth;
702 uint32_t auth_length;
704 if (!c->security_state.auth_info ||
705 !c->security_state.generic_state) {
709 switch (c->security_state.auth_info->auth_level) {
710 case DCERPC_AUTH_LEVEL_PRIVACY:
711 case DCERPC_AUTH_LEVEL_INTEGRITY:
714 case DCERPC_AUTH_LEVEL_CONNECT:
715 if (pkt->auth_length != 0) {
719 case DCERPC_AUTH_LEVEL_NONE:
720 if (pkt->auth_length != 0) {
721 return NT_STATUS_INVALID_NETWORK_RESPONSE;
726 return NT_STATUS_INVALID_LEVEL;
729 status = dcerpc_pull_auth_trailer(pkt, mem_ctx,
730 &pkt->u.response.stub_and_verifier,
731 &auth, &auth_length, false);
732 NT_STATUS_NOT_OK_RETURN(status);
734 pkt->u.response.stub_and_verifier.length -= auth_length;
736 /* check signature or unseal the packet */
737 switch (c->security_state.auth_info->auth_level) {
738 case DCERPC_AUTH_LEVEL_PRIVACY:
739 status = gensec_unseal_packet(c->security_state.generic_state,
740 raw_packet->data + DCERPC_REQUEST_LENGTH,
741 pkt->u.response.stub_and_verifier.length,
743 raw_packet->length - auth.credentials.length,
745 memcpy(pkt->u.response.stub_and_verifier.data,
746 raw_packet->data + DCERPC_REQUEST_LENGTH,
747 pkt->u.response.stub_and_verifier.length);
750 case DCERPC_AUTH_LEVEL_INTEGRITY:
751 status = gensec_check_packet(c->security_state.generic_state,
752 pkt->u.response.stub_and_verifier.data,
753 pkt->u.response.stub_and_verifier.length,
755 raw_packet->length - auth.credentials.length,
759 case DCERPC_AUTH_LEVEL_CONNECT:
760 /* for now we ignore possible signatures here */
761 status = NT_STATUS_OK;
765 status = NT_STATUS_INVALID_LEVEL;
769 /* remove the indicated amount of padding */
770 if (pkt->u.response.stub_and_verifier.length < auth.auth_pad_length) {
771 return NT_STATUS_INFO_LENGTH_MISMATCH;
773 pkt->u.response.stub_and_verifier.length -= auth.auth_pad_length;
780 push a dcerpc request packet into a blob, possibly signing it.
782 static NTSTATUS ncacn_push_request_sign(struct dcecli_connection *c,
783 DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
785 struct ncacn_packet *pkt)
788 struct ndr_push *ndr;
790 size_t payload_length;
791 enum ndr_err_code ndr_err;
792 size_t hdr_size = DCERPC_REQUEST_LENGTH;
794 /* non-signed packets are simpler */
796 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
799 switch (c->security_state.auth_info->auth_level) {
800 case DCERPC_AUTH_LEVEL_PRIVACY:
801 case DCERPC_AUTH_LEVEL_INTEGRITY:
804 case DCERPC_AUTH_LEVEL_CONNECT:
805 /* TODO: let the gensec mech decide if it wants to generate a signature */
806 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
808 case DCERPC_AUTH_LEVEL_NONE:
809 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
812 return NT_STATUS_INVALID_LEVEL;
815 ndr = ndr_push_init_ctx(mem_ctx);
817 return NT_STATUS_NO_MEMORY;
820 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
821 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
824 if (c->flags & DCERPC_NDR64) {
825 ndr->flags |= LIBNDR_FLAG_NDR64;
828 if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
829 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
833 ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
834 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
835 return ndr_map_error2ntstatus(ndr_err);
838 /* pad to 16 byte multiple in the payload portion of the
839 packet. This matches what w2k3 does. Note that we can't use
840 ndr_push_align() as that is relative to the start of the
841 whole packet, whereas w2k8 wants it relative to the start
843 c->security_state.auth_info->auth_pad_length =
844 (16 - (pkt->u.request.stub_and_verifier.length & 15)) & 15;
845 ndr_err = ndr_push_zero(ndr, c->security_state.auth_info->auth_pad_length);
846 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
847 return ndr_map_error2ntstatus(ndr_err);
850 payload_length = pkt->u.request.stub_and_verifier.length +
851 c->security_state.auth_info->auth_pad_length;
853 /* we start without signature, it will appended later */
854 c->security_state.auth_info->credentials = data_blob(NULL,0);
856 /* add the auth verifier */
857 ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, c->security_state.auth_info);
858 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
859 return ndr_map_error2ntstatus(ndr_err);
862 /* extract the whole packet as a blob */
863 *blob = ndr_push_blob(ndr);
866 * Setup the frag and auth length in the packet buffer.
867 * This is needed if the GENSEC mech does AEAD signing
868 * of the packet headers. The signature itself will be
871 dcerpc_set_frag_length(blob, blob->length + sig_size);
872 dcerpc_set_auth_length(blob, sig_size);
874 /* sign or seal the packet */
875 switch (c->security_state.auth_info->auth_level) {
876 case DCERPC_AUTH_LEVEL_PRIVACY:
877 status = gensec_seal_packet(c->security_state.generic_state,
879 blob->data + hdr_size,
884 if (!NT_STATUS_IS_OK(status)) {
889 case DCERPC_AUTH_LEVEL_INTEGRITY:
890 status = gensec_sign_packet(c->security_state.generic_state,
892 blob->data + hdr_size,
897 if (!NT_STATUS_IS_OK(status)) {
903 status = NT_STATUS_INVALID_LEVEL;
907 if (creds2.length != sig_size) {
908 /* this means the sig_size estimate for the signature
909 was incorrect. We have to correct the packet
910 sizes. That means we could go over the max fragment
912 DEBUG(3,("ncacn_push_request_sign: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n",
913 (unsigned) creds2.length,
915 (unsigned) c->security_state.auth_info->auth_pad_length,
916 (unsigned) pkt->u.request.stub_and_verifier.length));
917 dcerpc_set_frag_length(blob, blob->length + creds2.length);
918 dcerpc_set_auth_length(blob, creds2.length);
921 if (!data_blob_append(mem_ctx, blob, creds2.data, creds2.length)) {
922 return NT_STATUS_NO_MEMORY;
930 fill in the fixed values in a dcerpc header
932 static void init_ncacn_hdr(struct dcecli_connection *c, struct ncacn_packet *pkt)
935 pkt->rpc_vers_minor = 0;
936 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
939 pkt->drep[0] = DCERPC_DREP_LE;
947 map a bind nak reason to a NTSTATUS
949 static NTSTATUS dcerpc_map_reason(uint16_t reason)
952 case DCERPC_BIND_REASON_ASYNTAX:
953 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
954 case DCERPC_BIND_REASON_INVALID_AUTH_TYPE:
955 return NT_STATUS_INVALID_PARAMETER;
957 return NT_STATUS_UNSUCCESSFUL;
961 a bind or alter context has failed
963 static void dcerpc_composite_fail(struct rpc_request *req)
965 struct composite_context *c = talloc_get_type(req->async.private_data,
966 struct composite_context);
967 composite_error(c, req->status);
971 remove requests from the pending or queued queues
973 static int dcerpc_req_dequeue(struct rpc_request *req)
975 switch (req->state) {
976 case RPC_REQUEST_QUEUED:
977 DLIST_REMOVE(req->p->conn->request_queue, req);
979 case RPC_REQUEST_PENDING:
980 DLIST_REMOVE(req->p->conn->pending, req);
982 case RPC_REQUEST_DONE:
990 mark the dcerpc connection dead. All outstanding requests get an error
992 static void dcerpc_connection_dead(struct dcecli_connection *conn, NTSTATUS status)
994 if (conn->dead) return;
998 TALLOC_FREE(conn->io_trigger);
999 conn->io_trigger_pending = false;
1001 conn->transport.recv_data = NULL;
1003 if (conn->transport.shutdown_pipe) {
1004 conn->transport.shutdown_pipe(conn, status);
1007 /* all pending requests get the error */
1008 while (conn->pending) {
1009 struct rpc_request *req = conn->pending;
1010 dcerpc_req_dequeue(req);
1011 req->state = RPC_REQUEST_DONE;
1012 req->status = status;
1013 if (req->async.callback) {
1014 req->async.callback(req);
1018 /* all requests, which are not shipped */
1019 while (conn->request_queue) {
1020 struct rpc_request *req = conn->request_queue;
1021 dcerpc_req_dequeue(req);
1022 req->state = RPC_REQUEST_DONE;
1023 req->status = status;
1024 if (req->async.callback) {
1025 req->async.callback(req);
1029 talloc_set_destructor(conn, NULL);
1030 if (conn->free_skipped) {
1036 forward declarations of the recv_data handlers for the types of
1037 packets we need to handle
1039 static void dcerpc_request_recv_data(struct dcecli_connection *c,
1040 DATA_BLOB *raw_packet, struct ncacn_packet *pkt);
1043 receive a dcerpc reply from the transport. Here we work out what
1044 type of reply it is (normal request, bind or alter context) and
1045 dispatch to the appropriate handler
1047 static void dcerpc_recv_data(struct dcecli_connection *conn, DATA_BLOB *blob, NTSTATUS status)
1049 struct ncacn_packet pkt;
1051 if (NT_STATUS_IS_OK(status) && blob->length == 0) {
1052 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
1055 /* the transport may be telling us of a severe error, such as
1057 if (!NT_STATUS_IS_OK(status)) {
1058 data_blob_free(blob);
1059 dcerpc_connection_dead(conn, status);
1063 /* parse the basic packet to work out what type of response this is */
1064 status = ncacn_pull(conn, blob, blob->data, &pkt);
1065 if (!NT_STATUS_IS_OK(status)) {
1066 data_blob_free(blob);
1067 dcerpc_connection_dead(conn, status);
1071 dcerpc_request_recv_data(conn, blob, &pkt);
1075 Receive a bind reply from the transport
1077 static void dcerpc_bind_recv_handler(struct rpc_request *req,
1078 DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
1080 struct composite_context *c;
1081 struct dcecli_connection *conn;
1083 c = talloc_get_type(req->async.private_data, struct composite_context);
1085 if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
1086 DEBUG(2,("dcerpc: bind_nak reason %d\n",
1087 pkt->u.bind_nak.reject_reason));
1088 composite_error(c, dcerpc_map_reason(pkt->u.bind_nak.
1093 if ((pkt->ptype != DCERPC_PKT_BIND_ACK) ||
1094 (pkt->u.bind_ack.num_results == 0) ||
1095 (pkt->u.bind_ack.ctx_list[0].result != 0)) {
1096 req->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1097 composite_error(c, NT_STATUS_NET_WRITE_FAULT);
1101 conn = req->p->conn;
1103 conn->srv_max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1104 conn->srv_max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1106 if ((req->p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) &&
1107 (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX)) {
1108 conn->flags |= DCERPC_CONCURRENT_MULTIPLEX;
1111 if ((req->p->binding->flags & DCERPC_HEADER_SIGNING) &&
1112 (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
1113 conn->flags |= DCERPC_HEADER_SIGNING;
1116 /* the bind_ack might contain a reply set of credentials */
1117 if (conn->security_state.auth_info && pkt->u.bind_ack.auth_info.length) {
1119 uint32_t auth_length;
1120 status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.bind_ack.auth_info,
1121 conn->security_state.auth_info, &auth_length, true);
1122 if (!NT_STATUS_IS_OK(status)) {
1123 composite_error(c, status);
1128 req->p->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
1134 handle timeouts of individual dcerpc requests
1136 static void dcerpc_timeout_handler(struct tevent_context *ev, struct tevent_timer *te,
1137 struct timeval t, void *private_data)
1139 struct rpc_request *req = talloc_get_type(private_data, struct rpc_request);
1141 if (req->ignore_timeout) {
1142 dcerpc_req_dequeue(req);
1143 req->state = RPC_REQUEST_DONE;
1144 req->status = NT_STATUS_IO_TIMEOUT;
1145 if (req->async.callback) {
1146 req->async.callback(req);
1151 dcerpc_connection_dead(req->p->conn, NT_STATUS_IO_TIMEOUT);
1155 send a async dcerpc bind request
1157 struct composite_context *dcerpc_bind_send(struct dcerpc_pipe *p,
1158 TALLOC_CTX *mem_ctx,
1159 const struct ndr_syntax_id *syntax,
1160 const struct ndr_syntax_id *transfer_syntax)
1162 struct composite_context *c;
1163 struct ncacn_packet pkt;
1165 struct rpc_request *req;
1167 c = composite_create(mem_ctx,p->conn->event_ctx);
1168 if (c == NULL) return NULL;
1170 c->private_data = p;
1172 p->syntax = *syntax;
1173 p->transfer_syntax = *transfer_syntax;
1175 init_ncacn_hdr(p->conn, &pkt);
1177 pkt.ptype = DCERPC_PKT_BIND;
1178 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1179 pkt.call_id = p->conn->call_id;
1180 pkt.auth_length = 0;
1182 if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {
1183 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1186 if (p->binding->flags & DCERPC_HEADER_SIGNING) {
1187 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1190 pkt.u.bind.max_xmit_frag = 5840;
1191 pkt.u.bind.max_recv_frag = 5840;
1192 pkt.u.bind.assoc_group_id = p->binding->assoc_group_id;
1193 pkt.u.bind.num_contexts = 1;
1194 pkt.u.bind.ctx_list = talloc_array(mem_ctx, struct dcerpc_ctx_list, 1);
1195 if (composite_nomem(pkt.u.bind.ctx_list, c)) return c;
1196 pkt.u.bind.ctx_list[0].context_id = p->context_id;
1197 pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1;
1198 pkt.u.bind.ctx_list[0].abstract_syntax = p->syntax;
1199 pkt.u.bind.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
1200 pkt.u.bind.auth_info = data_blob(NULL, 0);
1202 /* construct the NDR form of the packet */
1203 c->status = ncacn_push_auth(&blob, c, &pkt,
1204 p->conn->security_state.auth_info);
1205 if (!composite_is_ok(c)) return c;
1207 p->conn->transport.recv_data = dcerpc_recv_data;
1210 * we allocate a dcerpc_request so we can be in the same
1211 * request queue as normal requests
1213 req = talloc_zero(c, struct rpc_request);
1214 if (composite_nomem(req, c)) return c;
1216 req->state = RPC_REQUEST_PENDING;
1217 req->call_id = pkt.call_id;
1218 req->async.private_data = c;
1219 req->async.callback = dcerpc_composite_fail;
1221 req->recv_handler = dcerpc_bind_recv_handler;
1222 DLIST_ADD_END(p->conn->pending, req, struct rpc_request *);
1223 talloc_set_destructor(req, dcerpc_req_dequeue);
1225 c->status = p->conn->transport.send_request(p->conn, &blob,
1227 if (!composite_is_ok(c)) return c;
1229 tevent_add_timer(c->event_ctx, req,
1230 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
1231 dcerpc_timeout_handler, req);
1237 recv side of async dcerpc bind request
1239 NTSTATUS dcerpc_bind_recv(struct composite_context *ctx)
1241 NTSTATUS result = composite_wait(ctx);
1247 perform a continued bind (and auth3)
1249 NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p,
1250 TALLOC_CTX *mem_ctx)
1252 struct ncacn_packet pkt;
1256 init_ncacn_hdr(p->conn, &pkt);
1258 pkt.ptype = DCERPC_PKT_AUTH3;
1259 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1260 pkt.call_id = next_call_id(p->conn);
1261 pkt.auth_length = 0;
1262 pkt.u.auth3.auth_info = data_blob(NULL, 0);
1264 if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {
1265 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1268 if (p->binding->flags & DCERPC_HEADER_SIGNING) {
1269 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1272 /* construct the NDR form of the packet */
1273 status = ncacn_push_auth(&blob, mem_ctx,
1275 p->conn->security_state.auth_info);
1276 if (!NT_STATUS_IS_OK(status)) {
1280 /* send it on its way */
1281 status = p->conn->transport.send_request(p->conn, &blob, false);
1282 if (!NT_STATUS_IS_OK(status)) {
1286 return NT_STATUS_OK;
1291 process a fragment received from the transport layer during a
1294 This function frees the data
1296 static void dcerpc_request_recv_data(struct dcecli_connection *c,
1297 DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
1299 struct rpc_request *req;
1300 unsigned int length;
1301 NTSTATUS status = NT_STATUS_OK;
1304 if this is an authenticated connection then parse and check
1305 the auth info. We have to do this before finding the
1306 matching packet, as the request structure might have been
1307 removed due to a timeout, but if it has been we still need
1308 to run the auth routines so that we don't get the sign/seal
1309 info out of step with the server
1311 if (c->security_state.auth_info && c->security_state.generic_state &&
1312 pkt->ptype == DCERPC_PKT_RESPONSE) {
1313 status = ncacn_pull_request_auth(c, raw_packet->data, raw_packet, pkt);
1316 /* find the matching request */
1317 for (req=c->pending;req;req=req->next) {
1318 if (pkt->call_id == req->call_id) break;
1322 /* useful for testing certain vendors RPC servers */
1323 if (req == NULL && c->pending && pkt->call_id == 0) {
1324 DEBUG(0,("HACK FOR INCORRECT CALL ID\n"));
1330 DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt->call_id));
1331 data_blob_free(raw_packet);
1335 talloc_steal(req, raw_packet->data);
1337 if (req->recv_handler != NULL) {
1338 dcerpc_req_dequeue(req);
1339 req->state = RPC_REQUEST_DONE;
1340 req->recv_handler(req, raw_packet, pkt);
1344 if (pkt->ptype == DCERPC_PKT_FAULT) {
1345 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
1346 req->fault_code = pkt->u.fault.status;
1347 req->status = NT_STATUS_NET_WRITE_FAULT;
1351 if (pkt->ptype != DCERPC_PKT_RESPONSE) {
1352 DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
1354 req->fault_code = DCERPC_FAULT_OTHER;
1355 req->status = NT_STATUS_NET_WRITE_FAULT;
1359 /* now check the status from the auth routines, and if it failed then fail
1360 this request accordingly */
1361 if (!NT_STATUS_IS_OK(status)) {
1362 req->status = status;
1366 length = pkt->u.response.stub_and_verifier.length;
1369 req->payload.data = talloc_realloc(req,
1372 req->payload.length + length);
1373 if (!req->payload.data) {
1374 req->status = NT_STATUS_NO_MEMORY;
1377 memcpy(req->payload.data+req->payload.length,
1378 pkt->u.response.stub_and_verifier.data, length);
1379 req->payload.length += length;
1382 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1383 c->transport.send_read(c);
1387 if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
1388 req->flags |= DCERPC_PULL_BIGENDIAN;
1390 req->flags &= ~DCERPC_PULL_BIGENDIAN;
1395 /* we've got the full payload */
1396 req->state = RPC_REQUEST_DONE;
1397 DLIST_REMOVE(c->pending, req);
1400 * We have to look at shipping further requests before calling
1401 * the async function, that one might close the pipe
1403 dcerpc_schedule_io_trigger(c);
1405 if (req->async.callback) {
1406 req->async.callback(req);
1411 perform the send side of a async dcerpc request
1413 static struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p,
1414 const struct GUID *object,
1416 DATA_BLOB *stub_data)
1418 struct rpc_request *req;
1420 p->conn->transport.recv_data = dcerpc_recv_data;
1422 req = talloc(p, struct rpc_request);
1428 req->call_id = next_call_id(p->conn);
1429 req->status = NT_STATUS_OK;
1430 req->state = RPC_REQUEST_QUEUED;
1431 req->payload = data_blob(NULL, 0);
1433 req->fault_code = 0;
1434 req->ignore_timeout = false;
1435 req->async.callback = NULL;
1436 req->async.private_data = NULL;
1437 req->recv_handler = NULL;
1439 if (object != NULL) {
1440 req->object = (struct GUID *)talloc_memdup(req, (const void *)object, sizeof(*object));
1441 if (req->object == NULL) {
1450 req->request_data.length = stub_data->length;
1451 req->request_data.data = talloc_reference(req, stub_data->data);
1452 if (req->request_data.length && req->request_data.data == NULL) {
1456 DLIST_ADD_END(p->conn->request_queue, req, struct rpc_request *);
1457 talloc_set_destructor(req, dcerpc_req_dequeue);
1459 dcerpc_schedule_io_trigger(p->conn);
1461 if (p->request_timeout) {
1462 tevent_add_timer(dcerpc_event_context(p), req,
1463 timeval_current_ofs(p->request_timeout, 0),
1464 dcerpc_timeout_handler, req);
1471 Send a request using the transport
1474 static void dcerpc_ship_next_request(struct dcecli_connection *c)
1476 struct rpc_request *req;
1477 struct dcerpc_pipe *p;
1478 DATA_BLOB *stub_data;
1479 struct ncacn_packet pkt;
1481 uint32_t remaining, chunk_size;
1482 bool first_packet = true;
1483 size_t sig_size = 0;
1484 bool need_async = false;
1486 req = c->request_queue;
1492 stub_data = &req->request_data;
1498 DLIST_REMOVE(c->request_queue, req);
1499 DLIST_ADD(c->pending, req);
1500 req->state = RPC_REQUEST_PENDING;
1502 init_ncacn_hdr(p->conn, &pkt);
1504 remaining = stub_data->length;
1506 /* we can write a full max_recv_frag size, minus the dcerpc
1507 request header size */
1508 chunk_size = p->conn->srv_max_recv_frag;
1509 chunk_size -= DCERPC_REQUEST_LENGTH;
1510 if (c->security_state.auth_info &&
1511 c->security_state.generic_state) {
1512 sig_size = gensec_sig_size(c->security_state.generic_state,
1513 p->conn->srv_max_recv_frag);
1515 chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
1516 chunk_size -= sig_size;
1519 chunk_size -= (chunk_size % 16);
1521 pkt.ptype = DCERPC_PKT_REQUEST;
1522 pkt.call_id = req->call_id;
1523 pkt.auth_length = 0;
1525 pkt.u.request.alloc_hint = remaining;
1526 pkt.u.request.context_id = p->context_id;
1527 pkt.u.request.opnum = req->opnum;
1530 pkt.u.request.object.object = *req->object;
1531 pkt.pfc_flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1532 chunk_size -= ndr_size_GUID(req->object,0);
1535 /* we send a series of pdus without waiting for a reply */
1536 while (remaining > 0 || first_packet) {
1537 uint32_t chunk = MIN(chunk_size, remaining);
1538 bool last_frag = false;
1539 bool do_trans = false;
1541 first_packet = false;
1542 pkt.pfc_flags &= ~(DCERPC_PFC_FLAG_FIRST |DCERPC_PFC_FLAG_LAST);
1544 if (remaining == stub_data->length) {
1545 pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST;
1547 if (chunk == remaining) {
1548 pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
1552 pkt.u.request.stub_and_verifier.data = stub_data->data +
1553 (stub_data->length - remaining);
1554 pkt.u.request.stub_and_verifier.length = chunk;
1556 req->status = ncacn_push_request_sign(p->conn, &blob, req, sig_size, &pkt);
1557 if (!NT_STATUS_IS_OK(req->status)) {
1558 req->state = RPC_REQUEST_DONE;
1559 DLIST_REMOVE(p->conn->pending, req);
1563 if (last_frag && !need_async) {
1567 req->status = p->conn->transport.send_request(p->conn, &blob, do_trans);
1568 if (!NT_STATUS_IS_OK(req->status)) {
1569 req->state = RPC_REQUEST_DONE;
1570 DLIST_REMOVE(p->conn->pending, req);
1574 if (last_frag && !do_trans) {
1575 req->status = p->conn->transport.send_read(p->conn);
1576 if (!NT_STATUS_IS_OK(req->status)) {
1577 req->state = RPC_REQUEST_DONE;
1578 DLIST_REMOVE(p->conn->pending, req);
1587 static void dcerpc_io_trigger(struct tevent_context *ctx,
1588 struct tevent_immediate *im,
1591 struct dcecli_connection *c =
1592 talloc_get_type_abort(private_data,
1593 struct dcecli_connection);
1595 c->io_trigger_pending = false;
1597 dcerpc_schedule_io_trigger(c);
1599 dcerpc_ship_next_request(c);
1602 static void dcerpc_schedule_io_trigger(struct dcecli_connection *c)
1608 if (c->request_queue == NULL) {
1612 if (c->io_trigger_pending) {
1616 c->io_trigger_pending = true;
1618 tevent_schedule_immediate(c->io_trigger,
1625 return the event context for a dcerpc pipe
1626 used by callers who wish to operate asynchronously
1628 _PUBLIC_ struct tevent_context *dcerpc_event_context(struct dcerpc_pipe *p)
1630 return p->conn->event_ctx;
1636 perform the receive side of a async dcerpc request
1638 static NTSTATUS dcerpc_request_recv(struct rpc_request *req,
1639 TALLOC_CTX *mem_ctx,
1640 DATA_BLOB *stub_data)
1644 while (req->state != RPC_REQUEST_DONE) {
1645 struct tevent_context *ctx = dcerpc_event_context(req->p);
1646 if (tevent_loop_once(ctx) != 0) {
1647 return NT_STATUS_CONNECTION_DISCONNECTED;
1650 *stub_data = req->payload;
1651 status = req->status;
1652 if (stub_data->data) {
1653 stub_data->data = talloc_steal(mem_ctx, stub_data->data);
1655 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
1656 req->p->last_fault_code = req->fault_code;
1658 talloc_unlink(talloc_parent(req), req);
1663 this is a paranoid NDR validator. For every packet we push onto the wire
1664 we pull it back again, then push it again. Then we compare the raw NDR data
1665 for that to the NDR we initially generated. If they don't match then we know
1666 we must have a bug in either the pull or push side of our code
1668 static NTSTATUS dcerpc_ndr_validate_in(struct dcecli_connection *c,
1669 TALLOC_CTX *mem_ctx,
1672 ndr_push_flags_fn_t ndr_push,
1673 ndr_pull_flags_fn_t ndr_pull)
1676 struct ndr_pull *pull;
1677 struct ndr_push *push;
1679 enum ndr_err_code ndr_err;
1681 st = talloc_size(mem_ctx, struct_size);
1683 return NT_STATUS_NO_MEMORY;
1686 pull = ndr_pull_init_flags(c, &blob, mem_ctx);
1688 return NT_STATUS_NO_MEMORY;
1690 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1692 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
1693 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1696 if (c->flags & DCERPC_NDR64) {
1697 pull->flags |= LIBNDR_FLAG_NDR64;
1700 ndr_err = ndr_pull(pull, NDR_IN, st);
1701 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1702 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1703 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1704 "failed input validation pull - %s",
1706 return ndr_map_error2ntstatus(ndr_err);
1709 push = ndr_push_init_ctx(mem_ctx);
1711 return NT_STATUS_NO_MEMORY;
1714 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
1715 push->flags |= LIBNDR_FLAG_BIGENDIAN;
1718 if (c->flags & DCERPC_NDR64) {
1719 push->flags |= LIBNDR_FLAG_NDR64;
1722 ndr_err = ndr_push(push, NDR_IN, st);
1723 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1724 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1725 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1726 "failed input validation push - %s",
1728 return ndr_map_error2ntstatus(ndr_err);
1731 blob2 = ndr_push_blob(push);
1733 if (data_blob_cmp(&blob, &blob2) != 0) {
1734 DEBUG(3,("original:\n"));
1735 dump_data(3, blob.data, blob.length);
1736 DEBUG(3,("secondary:\n"));
1737 dump_data(3, blob2.data, blob2.length);
1738 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1739 "failed input validation blobs doesn't match");
1740 return ndr_map_error2ntstatus(ndr_err);
1743 return NT_STATUS_OK;
1747 this is a paranoid NDR input validator. For every packet we pull
1748 from the wire we push it back again then pull and push it
1749 again. Then we compare the raw NDR data for that to the NDR we
1750 initially generated. If they don't match then we know we must have a
1751 bug in either the pull or push side of our code
1753 static NTSTATUS dcerpc_ndr_validate_out(struct dcecli_connection *c,
1754 struct ndr_pull *pull_in,
1757 ndr_push_flags_fn_t ndr_push,
1758 ndr_pull_flags_fn_t ndr_pull,
1759 ndr_print_function_t ndr_print)
1762 struct ndr_pull *pull;
1763 struct ndr_push *push;
1764 DATA_BLOB blob, blob2;
1765 TALLOC_CTX *mem_ctx = pull_in;
1767 enum ndr_err_code ndr_err;
1769 st = talloc_size(mem_ctx, struct_size);
1771 return NT_STATUS_NO_MEMORY;
1773 memcpy(st, struct_ptr, struct_size);
1775 push = ndr_push_init_ctx(mem_ctx);
1777 return NT_STATUS_NO_MEMORY;
1780 ndr_err = ndr_push(push, NDR_OUT, struct_ptr);
1781 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1782 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1783 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1784 "failed output validation push - %s",
1786 return ndr_map_error2ntstatus(ndr_err);
1789 blob = ndr_push_blob(push);
1791 pull = ndr_pull_init_flags(c, &blob, mem_ctx);
1793 return NT_STATUS_NO_MEMORY;
1796 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1797 ndr_err = ndr_pull(pull, NDR_OUT, st);
1798 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1799 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1800 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1801 "failed output validation pull - %s",
1803 return ndr_map_error2ntstatus(ndr_err);
1806 push = ndr_push_init_ctx(mem_ctx);
1808 return NT_STATUS_NO_MEMORY;
1811 ndr_err = ndr_push(push, NDR_OUT, st);
1812 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1813 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1814 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1815 "failed output validation push2 - %s",
1817 return ndr_map_error2ntstatus(ndr_err);
1820 blob2 = ndr_push_blob(push);
1822 if (data_blob_cmp(&blob, &blob2) != 0) {
1823 DEBUG(3,("original:\n"));
1824 dump_data(3, blob.data, blob.length);
1825 DEBUG(3,("secondary:\n"));
1826 dump_data(3, blob2.data, blob2.length);
1827 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1828 "failed output validation blobs doesn't match");
1829 return ndr_map_error2ntstatus(ndr_err);
1832 /* this checks the printed forms of the two structures, which effectively
1833 tests all of the value() attributes */
1834 s1 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE",
1835 NDR_OUT, struct_ptr);
1836 s2 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE",
1838 if (strcmp(s1, s2) != 0) {
1840 DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1, s2));
1842 /* this is sometimes useful */
1843 printf("VALIDATE ERROR\n");
1844 file_save("wire.dat", s1, strlen(s1));
1845 file_save("gen.dat", s2, strlen(s2));
1846 system("diff -u wire.dat gen.dat");
1848 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1849 "failed output validation strings doesn't match");
1850 return ndr_map_error2ntstatus(ndr_err);
1853 return NT_STATUS_OK;
1857 a useful function for retrieving the server name we connected to
1859 _PUBLIC_ const char *dcerpc_server_name(struct dcerpc_pipe *p)
1861 if (!p->conn->transport.target_hostname) {
1862 if (!p->conn->transport.peer_name) {
1865 return p->conn->transport.peer_name(p->conn);
1867 return p->conn->transport.target_hostname(p->conn);
1872 get the dcerpc auth_level for a open connection
1874 uint32_t dcerpc_auth_level(struct dcecli_connection *c)
1878 if (c->flags & DCERPC_SEAL) {
1879 auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1880 } else if (c->flags & DCERPC_SIGN) {
1881 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1882 } else if (c->flags & DCERPC_CONNECT) {
1883 auth_level = DCERPC_AUTH_LEVEL_CONNECT;
1885 auth_level = DCERPC_AUTH_LEVEL_NONE;
1891 Receive an alter reply from the transport
1893 static void dcerpc_alter_recv_handler(struct rpc_request *req,
1894 DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
1896 struct composite_context *c;
1897 struct dcerpc_pipe *recv_pipe;
1899 c = talloc_get_type(req->async.private_data, struct composite_context);
1900 recv_pipe = talloc_get_type(c->private_data, struct dcerpc_pipe);
1902 if (pkt->ptype == DCERPC_PKT_ALTER_RESP &&
1903 pkt->u.alter_resp.num_results == 1 &&
1904 pkt->u.alter_resp.ctx_list[0].result != 0) {
1905 DEBUG(2,("dcerpc: alter_resp failed - reason %d\n",
1906 pkt->u.alter_resp.ctx_list[0].reason));
1907 composite_error(c, dcerpc_map_reason(pkt->u.alter_resp.ctx_list[0].reason));
1911 if (pkt->ptype == DCERPC_PKT_FAULT) {
1912 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
1913 recv_pipe->last_fault_code = pkt->u.fault.status;
1914 composite_error(c, NT_STATUS_NET_WRITE_FAULT);
1918 if (pkt->ptype != DCERPC_PKT_ALTER_RESP ||
1919 pkt->u.alter_resp.num_results == 0 ||
1920 pkt->u.alter_resp.ctx_list[0].result != 0) {
1921 recv_pipe->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1922 composite_error(c, NT_STATUS_NET_WRITE_FAULT);
1926 /* the alter_resp might contain a reply set of credentials */
1927 if (recv_pipe->conn->security_state.auth_info &&
1928 pkt->u.alter_resp.auth_info.length) {
1929 struct dcecli_connection *conn = recv_pipe->conn;
1931 uint32_t auth_length;
1932 status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.alter_resp.auth_info,
1933 conn->security_state.auth_info, &auth_length, true);
1934 if (!NT_STATUS_IS_OK(status)) {
1935 composite_error(c, status);
1944 send a dcerpc alter_context request
1946 struct composite_context *dcerpc_alter_context_send(struct dcerpc_pipe *p,
1947 TALLOC_CTX *mem_ctx,
1948 const struct ndr_syntax_id *syntax,
1949 const struct ndr_syntax_id *transfer_syntax)
1951 struct composite_context *c;
1952 struct ncacn_packet pkt;
1954 struct rpc_request *req;
1956 c = composite_create(mem_ctx, p->conn->event_ctx);
1957 if (c == NULL) return NULL;
1959 c->private_data = p;
1961 p->syntax = *syntax;
1962 p->transfer_syntax = *transfer_syntax;
1964 init_ncacn_hdr(p->conn, &pkt);
1966 pkt.ptype = DCERPC_PKT_ALTER;
1967 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1968 pkt.call_id = p->conn->call_id;
1969 pkt.auth_length = 0;
1971 if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {
1972 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1975 if (p->binding->flags & DCERPC_HEADER_SIGNING) {
1976 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1979 pkt.u.alter.max_xmit_frag = 5840;
1980 pkt.u.alter.max_recv_frag = 5840;
1981 pkt.u.alter.assoc_group_id = p->binding->assoc_group_id;
1982 pkt.u.alter.num_contexts = 1;
1983 pkt.u.alter.ctx_list = talloc_array(c, struct dcerpc_ctx_list, 1);
1984 if (composite_nomem(pkt.u.alter.ctx_list, c)) return c;
1985 pkt.u.alter.ctx_list[0].context_id = p->context_id;
1986 pkt.u.alter.ctx_list[0].num_transfer_syntaxes = 1;
1987 pkt.u.alter.ctx_list[0].abstract_syntax = p->syntax;
1988 pkt.u.alter.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
1989 pkt.u.alter.auth_info = data_blob(NULL, 0);
1991 /* construct the NDR form of the packet */
1992 c->status = ncacn_push_auth(&blob, mem_ctx, &pkt,
1993 p->conn->security_state.auth_info);
1994 if (!composite_is_ok(c)) return c;
1996 p->conn->transport.recv_data = dcerpc_recv_data;
1999 * we allocate a dcerpc_request so we can be in the same
2000 * request queue as normal requests
2002 req = talloc_zero(c, struct rpc_request);
2003 if (composite_nomem(req, c)) return c;
2005 req->state = RPC_REQUEST_PENDING;
2006 req->call_id = pkt.call_id;
2007 req->async.private_data = c;
2008 req->async.callback = dcerpc_composite_fail;
2010 req->recv_handler = dcerpc_alter_recv_handler;
2011 DLIST_ADD_END(p->conn->pending, req, struct rpc_request *);
2012 talloc_set_destructor(req, dcerpc_req_dequeue);
2014 c->status = p->conn->transport.send_request(p->conn, &blob, true);
2015 if (!composite_is_ok(c)) return c;
2017 tevent_add_timer(c->event_ctx, req,
2018 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
2019 dcerpc_timeout_handler, req);
2024 NTSTATUS dcerpc_alter_context_recv(struct composite_context *ctx)
2026 NTSTATUS result = composite_wait(ctx);
2032 send a dcerpc alter_context request
2034 _PUBLIC_ NTSTATUS dcerpc_alter_context(struct dcerpc_pipe *p,
2035 TALLOC_CTX *mem_ctx,
2036 const struct ndr_syntax_id *syntax,
2037 const struct ndr_syntax_id *transfer_syntax)
2039 struct composite_context *creq;
2040 creq = dcerpc_alter_context_send(p, mem_ctx, syntax, transfer_syntax);
2041 return dcerpc_alter_context_recv(creq);