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 handle timeouts of individual dcerpc requests
1077 static void dcerpc_timeout_handler(struct tevent_context *ev, struct tevent_timer *te,
1078 struct timeval t, void *private_data)
1080 struct rpc_request *req = talloc_get_type(private_data, struct rpc_request);
1082 if (req->ignore_timeout) {
1083 dcerpc_req_dequeue(req);
1084 req->state = RPC_REQUEST_DONE;
1085 req->status = NT_STATUS_IO_TIMEOUT;
1086 if (req->async.callback) {
1087 req->async.callback(req);
1092 dcerpc_connection_dead(req->p->conn, NT_STATUS_IO_TIMEOUT);
1095 struct dcerpc_bind_state {
1096 struct dcerpc_pipe *p;
1099 static void dcerpc_bind_fail_handler(struct rpc_request *subreq);
1100 static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
1101 DATA_BLOB *raw_packet,
1102 struct ncacn_packet *pkt);
1104 struct tevent_req *dcerpc_bind_send(TALLOC_CTX *mem_ctx,
1105 struct tevent_context *ev,
1106 struct dcerpc_pipe *p,
1107 const struct ndr_syntax_id *syntax,
1108 const struct ndr_syntax_id *transfer_syntax)
1110 struct tevent_req *req;
1111 struct dcerpc_bind_state *state;
1112 struct ncacn_packet pkt;
1115 struct rpc_request *subreq;
1117 req = tevent_req_create(mem_ctx, &state,
1118 struct dcerpc_bind_state);
1125 p->syntax = *syntax;
1126 p->transfer_syntax = *transfer_syntax;
1128 init_ncacn_hdr(p->conn, &pkt);
1130 pkt.ptype = DCERPC_PKT_BIND;
1131 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1132 pkt.call_id = p->conn->call_id;
1133 pkt.auth_length = 0;
1135 if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {
1136 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1139 if (p->binding->flags & DCERPC_HEADER_SIGNING) {
1140 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1143 pkt.u.bind.max_xmit_frag = 5840;
1144 pkt.u.bind.max_recv_frag = 5840;
1145 pkt.u.bind.assoc_group_id = p->binding->assoc_group_id;
1146 pkt.u.bind.num_contexts = 1;
1147 pkt.u.bind.ctx_list = talloc_array(mem_ctx, struct dcerpc_ctx_list, 1);
1148 if (tevent_req_nomem(pkt.u.bind.ctx_list, req)) {
1149 return tevent_req_post(req, ev);
1151 pkt.u.bind.ctx_list[0].context_id = p->context_id;
1152 pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1;
1153 pkt.u.bind.ctx_list[0].abstract_syntax = p->syntax;
1154 pkt.u.bind.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
1155 pkt.u.bind.auth_info = data_blob(NULL, 0);
1157 /* construct the NDR form of the packet */
1158 status = ncacn_push_auth(&blob, state, &pkt,
1159 p->conn->security_state.auth_info);
1160 if (tevent_req_nterror(req, status)) {
1161 return tevent_req_post(req, ev);
1164 p->conn->transport.recv_data = dcerpc_recv_data;
1167 * we allocate a dcerpc_request so we can be in the same
1168 * request queue as normal requests
1170 subreq = talloc_zero(state, struct rpc_request);
1171 if (tevent_req_nomem(subreq, req)) {
1172 return tevent_req_post(req, ev);
1175 subreq->state = RPC_REQUEST_PENDING;
1176 subreq->call_id = pkt.call_id;
1177 subreq->async.private_data = req;
1178 subreq->async.callback = dcerpc_bind_fail_handler;
1180 subreq->recv_handler = dcerpc_bind_recv_handler;
1181 DLIST_ADD_END(p->conn->pending, subreq, struct rpc_request *);
1182 talloc_set_destructor(subreq, dcerpc_req_dequeue);
1184 status = p->conn->transport.send_request(p->conn, &blob, true);
1185 if (tevent_req_nterror(req, status)) {
1186 return tevent_req_post(req, ev);
1189 tevent_add_timer(ev, subreq,
1190 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
1191 dcerpc_timeout_handler, subreq);
1196 static void dcerpc_bind_fail_handler(struct rpc_request *subreq)
1198 struct tevent_req *req =
1199 talloc_get_type_abort(subreq->async.private_data,
1201 NTSTATUS status = subreq->status;
1203 TALLOC_FREE(subreq);
1205 tevent_req_nterror(req, status);
1208 static void dcerpc_bind_recv_handler(struct rpc_request *subreq,
1209 DATA_BLOB *raw_packet,
1210 struct ncacn_packet *pkt)
1212 struct tevent_req *req =
1213 talloc_get_type_abort(subreq->async.private_data,
1215 struct dcerpc_bind_state *state =
1216 tevent_req_data(req,
1217 struct dcerpc_bind_state);
1218 struct dcecli_connection *conn = state->p->conn;
1222 * Note that pkt is allocated under raw_packet->data,
1223 * while raw_packet->data is a child of subreq.
1225 talloc_steal(state, raw_packet->data);
1226 TALLOC_FREE(subreq);
1228 if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
1229 status = dcerpc_map_reason(pkt->u.bind_nak.reject_reason);
1231 DEBUG(2,("dcerpc: bind_nak reason %d - %s\n",
1232 pkt->u.bind_nak.reject_reason, nt_errstr(status)));
1234 tevent_req_nterror(req, status);
1238 if ((pkt->ptype != DCERPC_PKT_BIND_ACK) ||
1239 (pkt->u.bind_ack.num_results == 0) ||
1240 (pkt->u.bind_ack.ctx_list[0].result != 0)) {
1241 state->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1242 tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
1246 conn->srv_max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1247 conn->srv_max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1249 if ((state->p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) &&
1250 (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX)) {
1251 conn->flags |= DCERPC_CONCURRENT_MULTIPLEX;
1254 if ((state->p->binding->flags & DCERPC_HEADER_SIGNING) &&
1255 (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
1256 conn->flags |= DCERPC_HEADER_SIGNING;
1259 /* the bind_ack might contain a reply set of credentials */
1260 if (conn->security_state.auth_info && pkt->u.bind_ack.auth_info.length) {
1261 uint32_t auth_length;
1263 status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.bind_ack.auth_info,
1264 conn->security_state.auth_info, &auth_length, true);
1265 if (tevent_req_nterror(req, status)) {
1270 state->p->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
1272 tevent_req_done(req);
1275 NTSTATUS dcerpc_bind_recv(struct tevent_req *req)
1277 return tevent_req_simple_recv_ntstatus(req);
1281 perform a continued bind (and auth3)
1283 NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p,
1284 TALLOC_CTX *mem_ctx)
1286 struct ncacn_packet pkt;
1290 init_ncacn_hdr(p->conn, &pkt);
1292 pkt.ptype = DCERPC_PKT_AUTH3;
1293 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1294 pkt.call_id = next_call_id(p->conn);
1295 pkt.auth_length = 0;
1296 pkt.u.auth3.auth_info = data_blob(NULL, 0);
1298 if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {
1299 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1302 if (p->binding->flags & DCERPC_HEADER_SIGNING) {
1303 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1306 /* construct the NDR form of the packet */
1307 status = ncacn_push_auth(&blob, mem_ctx,
1309 p->conn->security_state.auth_info);
1310 if (!NT_STATUS_IS_OK(status)) {
1314 /* send it on its way */
1315 status = p->conn->transport.send_request(p->conn, &blob, false);
1316 if (!NT_STATUS_IS_OK(status)) {
1320 return NT_STATUS_OK;
1325 process a fragment received from the transport layer during a
1328 This function frees the data
1330 static void dcerpc_request_recv_data(struct dcecli_connection *c,
1331 DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
1333 struct rpc_request *req;
1334 unsigned int length;
1335 NTSTATUS status = NT_STATUS_OK;
1338 if this is an authenticated connection then parse and check
1339 the auth info. We have to do this before finding the
1340 matching packet, as the request structure might have been
1341 removed due to a timeout, but if it has been we still need
1342 to run the auth routines so that we don't get the sign/seal
1343 info out of step with the server
1345 if (c->security_state.auth_info && c->security_state.generic_state &&
1346 pkt->ptype == DCERPC_PKT_RESPONSE) {
1347 status = ncacn_pull_request_auth(c, raw_packet->data, raw_packet, pkt);
1350 /* find the matching request */
1351 for (req=c->pending;req;req=req->next) {
1352 if (pkt->call_id == req->call_id) break;
1356 /* useful for testing certain vendors RPC servers */
1357 if (req == NULL && c->pending && pkt->call_id == 0) {
1358 DEBUG(0,("HACK FOR INCORRECT CALL ID\n"));
1364 DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt->call_id));
1365 data_blob_free(raw_packet);
1369 talloc_steal(req, raw_packet->data);
1371 if (req->recv_handler != NULL) {
1372 dcerpc_req_dequeue(req);
1373 req->state = RPC_REQUEST_DONE;
1374 req->recv_handler(req, raw_packet, pkt);
1378 if (pkt->ptype == DCERPC_PKT_FAULT) {
1379 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
1380 req->fault_code = pkt->u.fault.status;
1381 req->status = NT_STATUS_NET_WRITE_FAULT;
1385 if (pkt->ptype != DCERPC_PKT_RESPONSE) {
1386 DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
1388 req->fault_code = DCERPC_FAULT_OTHER;
1389 req->status = NT_STATUS_NET_WRITE_FAULT;
1393 /* now check the status from the auth routines, and if it failed then fail
1394 this request accordingly */
1395 if (!NT_STATUS_IS_OK(status)) {
1396 req->status = status;
1400 length = pkt->u.response.stub_and_verifier.length;
1403 req->payload.data = talloc_realloc(req,
1406 req->payload.length + length);
1407 if (!req->payload.data) {
1408 req->status = NT_STATUS_NO_MEMORY;
1411 memcpy(req->payload.data+req->payload.length,
1412 pkt->u.response.stub_and_verifier.data, length);
1413 req->payload.length += length;
1416 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1417 c->transport.send_read(c);
1421 if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
1422 req->flags |= DCERPC_PULL_BIGENDIAN;
1424 req->flags &= ~DCERPC_PULL_BIGENDIAN;
1429 /* we've got the full payload */
1430 req->state = RPC_REQUEST_DONE;
1431 DLIST_REMOVE(c->pending, req);
1434 * We have to look at shipping further requests before calling
1435 * the async function, that one might close the pipe
1437 dcerpc_schedule_io_trigger(c);
1439 if (req->async.callback) {
1440 req->async.callback(req);
1445 perform the send side of a async dcerpc request
1447 static struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p,
1448 const struct GUID *object,
1450 DATA_BLOB *stub_data)
1452 struct rpc_request *req;
1454 p->conn->transport.recv_data = dcerpc_recv_data;
1456 req = talloc(p, struct rpc_request);
1462 req->call_id = next_call_id(p->conn);
1463 req->status = NT_STATUS_OK;
1464 req->state = RPC_REQUEST_QUEUED;
1465 req->payload = data_blob(NULL, 0);
1467 req->fault_code = 0;
1468 req->ignore_timeout = false;
1469 req->async.callback = NULL;
1470 req->async.private_data = NULL;
1471 req->recv_handler = NULL;
1473 if (object != NULL) {
1474 req->object = (struct GUID *)talloc_memdup(req, (const void *)object, sizeof(*object));
1475 if (req->object == NULL) {
1484 req->request_data.length = stub_data->length;
1485 req->request_data.data = talloc_reference(req, stub_data->data);
1486 if (req->request_data.length && req->request_data.data == NULL) {
1490 DLIST_ADD_END(p->conn->request_queue, req, struct rpc_request *);
1491 talloc_set_destructor(req, dcerpc_req_dequeue);
1493 dcerpc_schedule_io_trigger(p->conn);
1495 if (p->request_timeout) {
1496 tevent_add_timer(dcerpc_event_context(p), req,
1497 timeval_current_ofs(p->request_timeout, 0),
1498 dcerpc_timeout_handler, req);
1505 Send a request using the transport
1508 static void dcerpc_ship_next_request(struct dcecli_connection *c)
1510 struct rpc_request *req;
1511 struct dcerpc_pipe *p;
1512 DATA_BLOB *stub_data;
1513 struct ncacn_packet pkt;
1515 uint32_t remaining, chunk_size;
1516 bool first_packet = true;
1517 size_t sig_size = 0;
1518 bool need_async = false;
1520 req = c->request_queue;
1526 stub_data = &req->request_data;
1532 DLIST_REMOVE(c->request_queue, req);
1533 DLIST_ADD(c->pending, req);
1534 req->state = RPC_REQUEST_PENDING;
1536 init_ncacn_hdr(p->conn, &pkt);
1538 remaining = stub_data->length;
1540 /* we can write a full max_recv_frag size, minus the dcerpc
1541 request header size */
1542 chunk_size = p->conn->srv_max_recv_frag;
1543 chunk_size -= DCERPC_REQUEST_LENGTH;
1544 if (c->security_state.auth_info &&
1545 c->security_state.generic_state) {
1546 sig_size = gensec_sig_size(c->security_state.generic_state,
1547 p->conn->srv_max_recv_frag);
1549 chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
1550 chunk_size -= sig_size;
1553 chunk_size -= (chunk_size % 16);
1555 pkt.ptype = DCERPC_PKT_REQUEST;
1556 pkt.call_id = req->call_id;
1557 pkt.auth_length = 0;
1559 pkt.u.request.alloc_hint = remaining;
1560 pkt.u.request.context_id = p->context_id;
1561 pkt.u.request.opnum = req->opnum;
1564 pkt.u.request.object.object = *req->object;
1565 pkt.pfc_flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1566 chunk_size -= ndr_size_GUID(req->object,0);
1569 /* we send a series of pdus without waiting for a reply */
1570 while (remaining > 0 || first_packet) {
1571 uint32_t chunk = MIN(chunk_size, remaining);
1572 bool last_frag = false;
1573 bool do_trans = false;
1575 first_packet = false;
1576 pkt.pfc_flags &= ~(DCERPC_PFC_FLAG_FIRST |DCERPC_PFC_FLAG_LAST);
1578 if (remaining == stub_data->length) {
1579 pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST;
1581 if (chunk == remaining) {
1582 pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
1586 pkt.u.request.stub_and_verifier.data = stub_data->data +
1587 (stub_data->length - remaining);
1588 pkt.u.request.stub_and_verifier.length = chunk;
1590 req->status = ncacn_push_request_sign(p->conn, &blob, req, sig_size, &pkt);
1591 if (!NT_STATUS_IS_OK(req->status)) {
1592 req->state = RPC_REQUEST_DONE;
1593 DLIST_REMOVE(p->conn->pending, req);
1597 if (last_frag && !need_async) {
1601 req->status = p->conn->transport.send_request(p->conn, &blob, do_trans);
1602 if (!NT_STATUS_IS_OK(req->status)) {
1603 req->state = RPC_REQUEST_DONE;
1604 DLIST_REMOVE(p->conn->pending, req);
1608 if (last_frag && !do_trans) {
1609 req->status = p->conn->transport.send_read(p->conn);
1610 if (!NT_STATUS_IS_OK(req->status)) {
1611 req->state = RPC_REQUEST_DONE;
1612 DLIST_REMOVE(p->conn->pending, req);
1621 static void dcerpc_io_trigger(struct tevent_context *ctx,
1622 struct tevent_immediate *im,
1625 struct dcecli_connection *c =
1626 talloc_get_type_abort(private_data,
1627 struct dcecli_connection);
1629 c->io_trigger_pending = false;
1631 dcerpc_schedule_io_trigger(c);
1633 dcerpc_ship_next_request(c);
1636 static void dcerpc_schedule_io_trigger(struct dcecli_connection *c)
1642 if (c->request_queue == NULL) {
1646 if (c->io_trigger_pending) {
1650 c->io_trigger_pending = true;
1652 tevent_schedule_immediate(c->io_trigger,
1659 return the event context for a dcerpc pipe
1660 used by callers who wish to operate asynchronously
1662 _PUBLIC_ struct tevent_context *dcerpc_event_context(struct dcerpc_pipe *p)
1664 return p->conn->event_ctx;
1670 perform the receive side of a async dcerpc request
1672 static NTSTATUS dcerpc_request_recv(struct rpc_request *req,
1673 TALLOC_CTX *mem_ctx,
1674 DATA_BLOB *stub_data)
1678 while (req->state != RPC_REQUEST_DONE) {
1679 struct tevent_context *ctx = dcerpc_event_context(req->p);
1680 if (tevent_loop_once(ctx) != 0) {
1681 return NT_STATUS_CONNECTION_DISCONNECTED;
1684 *stub_data = req->payload;
1685 status = req->status;
1686 if (stub_data->data) {
1687 stub_data->data = talloc_steal(mem_ctx, stub_data->data);
1689 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
1690 req->p->last_fault_code = req->fault_code;
1692 talloc_unlink(talloc_parent(req), req);
1697 this is a paranoid NDR validator. For every packet we push onto the wire
1698 we pull it back again, then push it again. Then we compare the raw NDR data
1699 for that to the NDR we initially generated. If they don't match then we know
1700 we must have a bug in either the pull or push side of our code
1702 static NTSTATUS dcerpc_ndr_validate_in(struct dcecli_connection *c,
1703 TALLOC_CTX *mem_ctx,
1706 ndr_push_flags_fn_t ndr_push,
1707 ndr_pull_flags_fn_t ndr_pull)
1710 struct ndr_pull *pull;
1711 struct ndr_push *push;
1713 enum ndr_err_code ndr_err;
1715 st = talloc_size(mem_ctx, struct_size);
1717 return NT_STATUS_NO_MEMORY;
1720 pull = ndr_pull_init_flags(c, &blob, mem_ctx);
1722 return NT_STATUS_NO_MEMORY;
1724 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1726 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
1727 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1730 if (c->flags & DCERPC_NDR64) {
1731 pull->flags |= LIBNDR_FLAG_NDR64;
1734 ndr_err = ndr_pull(pull, NDR_IN, st);
1735 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1736 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1737 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1738 "failed input validation pull - %s",
1740 return ndr_map_error2ntstatus(ndr_err);
1743 push = ndr_push_init_ctx(mem_ctx);
1745 return NT_STATUS_NO_MEMORY;
1748 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
1749 push->flags |= LIBNDR_FLAG_BIGENDIAN;
1752 if (c->flags & DCERPC_NDR64) {
1753 push->flags |= LIBNDR_FLAG_NDR64;
1756 ndr_err = ndr_push(push, NDR_IN, st);
1757 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1758 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1759 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1760 "failed input validation push - %s",
1762 return ndr_map_error2ntstatus(ndr_err);
1765 blob2 = ndr_push_blob(push);
1767 if (data_blob_cmp(&blob, &blob2) != 0) {
1768 DEBUG(3,("original:\n"));
1769 dump_data(3, blob.data, blob.length);
1770 DEBUG(3,("secondary:\n"));
1771 dump_data(3, blob2.data, blob2.length);
1772 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1773 "failed input validation blobs doesn't match");
1774 return ndr_map_error2ntstatus(ndr_err);
1777 return NT_STATUS_OK;
1781 this is a paranoid NDR input validator. For every packet we pull
1782 from the wire we push it back again then pull and push it
1783 again. Then we compare the raw NDR data for that to the NDR we
1784 initially generated. If they don't match then we know we must have a
1785 bug in either the pull or push side of our code
1787 static NTSTATUS dcerpc_ndr_validate_out(struct dcecli_connection *c,
1788 struct ndr_pull *pull_in,
1791 ndr_push_flags_fn_t ndr_push,
1792 ndr_pull_flags_fn_t ndr_pull,
1793 ndr_print_function_t ndr_print)
1796 struct ndr_pull *pull;
1797 struct ndr_push *push;
1798 DATA_BLOB blob, blob2;
1799 TALLOC_CTX *mem_ctx = pull_in;
1801 enum ndr_err_code ndr_err;
1803 st = talloc_size(mem_ctx, struct_size);
1805 return NT_STATUS_NO_MEMORY;
1807 memcpy(st, struct_ptr, struct_size);
1809 push = ndr_push_init_ctx(mem_ctx);
1811 return NT_STATUS_NO_MEMORY;
1814 ndr_err = ndr_push(push, NDR_OUT, struct_ptr);
1815 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1816 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1817 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1818 "failed output validation push - %s",
1820 return ndr_map_error2ntstatus(ndr_err);
1823 blob = ndr_push_blob(push);
1825 pull = ndr_pull_init_flags(c, &blob, mem_ctx);
1827 return NT_STATUS_NO_MEMORY;
1830 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1831 ndr_err = ndr_pull(pull, NDR_OUT, st);
1832 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1833 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1834 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1835 "failed output validation pull - %s",
1837 return ndr_map_error2ntstatus(ndr_err);
1840 push = ndr_push_init_ctx(mem_ctx);
1842 return NT_STATUS_NO_MEMORY;
1845 ndr_err = ndr_push(push, NDR_OUT, st);
1846 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1847 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1848 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1849 "failed output validation push2 - %s",
1851 return ndr_map_error2ntstatus(ndr_err);
1854 blob2 = ndr_push_blob(push);
1856 if (data_blob_cmp(&blob, &blob2) != 0) {
1857 DEBUG(3,("original:\n"));
1858 dump_data(3, blob.data, blob.length);
1859 DEBUG(3,("secondary:\n"));
1860 dump_data(3, blob2.data, blob2.length);
1861 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1862 "failed output validation blobs doesn't match");
1863 return ndr_map_error2ntstatus(ndr_err);
1866 /* this checks the printed forms of the two structures, which effectively
1867 tests all of the value() attributes */
1868 s1 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE",
1869 NDR_OUT, struct_ptr);
1870 s2 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE",
1872 if (strcmp(s1, s2) != 0) {
1874 DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1, s2));
1876 /* this is sometimes useful */
1877 printf("VALIDATE ERROR\n");
1878 file_save("wire.dat", s1, strlen(s1));
1879 file_save("gen.dat", s2, strlen(s2));
1880 system("diff -u wire.dat gen.dat");
1882 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1883 "failed output validation strings doesn't match");
1884 return ndr_map_error2ntstatus(ndr_err);
1887 return NT_STATUS_OK;
1891 a useful function for retrieving the server name we connected to
1893 _PUBLIC_ const char *dcerpc_server_name(struct dcerpc_pipe *p)
1895 if (!p->conn->transport.target_hostname) {
1896 if (!p->conn->transport.peer_name) {
1899 return p->conn->transport.peer_name(p->conn);
1901 return p->conn->transport.target_hostname(p->conn);
1906 get the dcerpc auth_level for a open connection
1908 uint32_t dcerpc_auth_level(struct dcecli_connection *c)
1912 if (c->flags & DCERPC_SEAL) {
1913 auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1914 } else if (c->flags & DCERPC_SIGN) {
1915 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1916 } else if (c->flags & DCERPC_CONNECT) {
1917 auth_level = DCERPC_AUTH_LEVEL_CONNECT;
1919 auth_level = DCERPC_AUTH_LEVEL_NONE;
1925 Receive an alter reply from the transport
1927 static void dcerpc_alter_recv_handler(struct rpc_request *req,
1928 DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
1930 struct composite_context *c;
1931 struct dcerpc_pipe *recv_pipe;
1933 c = talloc_get_type(req->async.private_data, struct composite_context);
1934 recv_pipe = talloc_get_type(c->private_data, struct dcerpc_pipe);
1936 if (pkt->ptype == DCERPC_PKT_ALTER_RESP &&
1937 pkt->u.alter_resp.num_results == 1 &&
1938 pkt->u.alter_resp.ctx_list[0].result != 0) {
1939 DEBUG(2,("dcerpc: alter_resp failed - reason %d\n",
1940 pkt->u.alter_resp.ctx_list[0].reason));
1941 composite_error(c, dcerpc_map_reason(pkt->u.alter_resp.ctx_list[0].reason));
1945 if (pkt->ptype == DCERPC_PKT_FAULT) {
1946 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
1947 recv_pipe->last_fault_code = pkt->u.fault.status;
1948 composite_error(c, NT_STATUS_NET_WRITE_FAULT);
1952 if (pkt->ptype != DCERPC_PKT_ALTER_RESP ||
1953 pkt->u.alter_resp.num_results == 0 ||
1954 pkt->u.alter_resp.ctx_list[0].result != 0) {
1955 recv_pipe->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1956 composite_error(c, NT_STATUS_NET_WRITE_FAULT);
1960 /* the alter_resp might contain a reply set of credentials */
1961 if (recv_pipe->conn->security_state.auth_info &&
1962 pkt->u.alter_resp.auth_info.length) {
1963 struct dcecli_connection *conn = recv_pipe->conn;
1965 uint32_t auth_length;
1966 status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.alter_resp.auth_info,
1967 conn->security_state.auth_info, &auth_length, true);
1968 if (!NT_STATUS_IS_OK(status)) {
1969 composite_error(c, status);
1978 send a dcerpc alter_context request
1980 struct composite_context *dcerpc_alter_context_send(struct dcerpc_pipe *p,
1981 TALLOC_CTX *mem_ctx,
1982 const struct ndr_syntax_id *syntax,
1983 const struct ndr_syntax_id *transfer_syntax)
1985 struct composite_context *c;
1986 struct ncacn_packet pkt;
1988 struct rpc_request *req;
1990 c = composite_create(mem_ctx, p->conn->event_ctx);
1991 if (c == NULL) return NULL;
1993 c->private_data = p;
1995 p->syntax = *syntax;
1996 p->transfer_syntax = *transfer_syntax;
1998 init_ncacn_hdr(p->conn, &pkt);
2000 pkt.ptype = DCERPC_PKT_ALTER;
2001 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
2002 pkt.call_id = p->conn->call_id;
2003 pkt.auth_length = 0;
2005 if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {
2006 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
2009 if (p->binding->flags & DCERPC_HEADER_SIGNING) {
2010 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
2013 pkt.u.alter.max_xmit_frag = 5840;
2014 pkt.u.alter.max_recv_frag = 5840;
2015 pkt.u.alter.assoc_group_id = p->binding->assoc_group_id;
2016 pkt.u.alter.num_contexts = 1;
2017 pkt.u.alter.ctx_list = talloc_array(c, struct dcerpc_ctx_list, 1);
2018 if (composite_nomem(pkt.u.alter.ctx_list, c)) return c;
2019 pkt.u.alter.ctx_list[0].context_id = p->context_id;
2020 pkt.u.alter.ctx_list[0].num_transfer_syntaxes = 1;
2021 pkt.u.alter.ctx_list[0].abstract_syntax = p->syntax;
2022 pkt.u.alter.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
2023 pkt.u.alter.auth_info = data_blob(NULL, 0);
2025 /* construct the NDR form of the packet */
2026 c->status = ncacn_push_auth(&blob, mem_ctx, &pkt,
2027 p->conn->security_state.auth_info);
2028 if (!composite_is_ok(c)) return c;
2030 p->conn->transport.recv_data = dcerpc_recv_data;
2033 * we allocate a dcerpc_request so we can be in the same
2034 * request queue as normal requests
2036 req = talloc_zero(c, struct rpc_request);
2037 if (composite_nomem(req, c)) return c;
2039 req->state = RPC_REQUEST_PENDING;
2040 req->call_id = pkt.call_id;
2041 req->async.private_data = c;
2042 req->async.callback = dcerpc_composite_fail;
2044 req->recv_handler = dcerpc_alter_recv_handler;
2045 DLIST_ADD_END(p->conn->pending, req, struct rpc_request *);
2046 talloc_set_destructor(req, dcerpc_req_dequeue);
2048 c->status = p->conn->transport.send_request(p->conn, &blob, true);
2049 if (!composite_is_ok(c)) return c;
2051 tevent_add_timer(c->event_ctx, req,
2052 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
2053 dcerpc_timeout_handler, req);
2058 NTSTATUS dcerpc_alter_context_recv(struct composite_context *ctx)
2060 NTSTATUS result = composite_wait(ctx);
2066 send a dcerpc alter_context request
2068 _PUBLIC_ NTSTATUS dcerpc_alter_context(struct dcerpc_pipe *p,
2069 TALLOC_CTX *mem_ctx,
2070 const struct ndr_syntax_id *syntax,
2071 const struct ndr_syntax_id *transfer_syntax)
2073 struct composite_context *creq;
2074 creq = dcerpc_alter_context_send(p, mem_ctx, syntax, transfer_syntax);
2075 return dcerpc_alter_context_recv(creq);