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"
35 _PUBLIC_ NTSTATUS dcerpc_init(struct loadparm_context *lp_ctx)
37 return gensec_init(lp_ctx);
40 static void dcerpc_connection_dead(struct dcerpc_connection *conn, NTSTATUS status);
41 static void dcerpc_ship_next_request(struct dcerpc_connection *c);
43 static struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p,
44 const struct GUID *object,
46 DATA_BLOB *stub_data);
47 static NTSTATUS dcerpc_ndr_validate_in(struct dcerpc_connection *c,
51 ndr_push_flags_fn_t ndr_push,
52 ndr_pull_flags_fn_t ndr_pull);
53 static NTSTATUS dcerpc_ndr_validate_out(struct dcerpc_connection *c,
54 struct ndr_pull *pull_in,
57 ndr_push_flags_fn_t ndr_push,
58 ndr_pull_flags_fn_t ndr_pull,
59 ndr_print_function_t ndr_print);
61 /* destroy a dcerpc connection */
62 static int dcerpc_connection_destructor(struct dcerpc_connection *conn)
65 conn->free_skipped = true;
68 dcerpc_connection_dead(conn, NT_STATUS_LOCAL_DISCONNECT);
73 /* initialise a dcerpc connection.
74 the event context is optional
76 static struct dcerpc_connection *dcerpc_connection_init(TALLOC_CTX *mem_ctx,
77 struct tevent_context *ev)
79 struct dcerpc_connection *c;
81 c = talloc_zero(mem_ctx, struct dcerpc_connection);
88 if (c->event_ctx == NULL) {
94 c->security_state.auth_info = NULL;
95 c->security_state.session_key = dcerpc_generic_session_key;
96 c->security_state.generic_state = NULL;
97 c->binding_string = NULL;
99 c->srv_max_xmit_frag = 0;
100 c->srv_max_recv_frag = 0;
103 talloc_set_destructor(c, dcerpc_connection_destructor);
108 struct dcerpc_bh_state {
109 struct dcerpc_pipe *p;
112 static bool dcerpc_bh_is_connected(struct dcerpc_binding_handle *h)
114 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
115 struct dcerpc_bh_state);
124 static uint32_t dcerpc_bh_set_timeout(struct dcerpc_binding_handle *h,
127 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
128 struct dcerpc_bh_state);
132 return DCERPC_REQUEST_TIMEOUT;
135 old = hs->p->request_timeout;
136 hs->p->request_timeout = timeout;
141 struct dcerpc_bh_raw_call_state {
142 struct dcerpc_binding_handle *h;
148 static void dcerpc_bh_raw_call_done(struct rpc_request *subreq);
150 static struct tevent_req *dcerpc_bh_raw_call_send(TALLOC_CTX *mem_ctx,
151 struct tevent_context *ev,
152 struct dcerpc_binding_handle *h,
153 const struct GUID *object,
156 const uint8_t *in_data,
159 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
160 struct dcerpc_bh_state);
161 struct tevent_req *req;
162 struct dcerpc_bh_raw_call_state *state;
164 struct rpc_request *subreq;
166 req = tevent_req_create(mem_ctx, &state,
167 struct dcerpc_bh_raw_call_state);
172 state->in_data.data = discard_const_p(uint8_t, in_data);
173 state->in_data.length = in_length;
175 ok = dcerpc_bh_is_connected(h);
177 tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
178 return tevent_req_post(req, ev);
181 subreq = dcerpc_request_send(hs->p,
185 if (tevent_req_nomem(subreq, req)) {
186 return tevent_req_post(req, ev);
188 subreq->async.callback = dcerpc_bh_raw_call_done;
189 subreq->async.private_data = req;
194 static void dcerpc_bh_raw_call_done(struct rpc_request *subreq)
196 struct tevent_req *req =
197 talloc_get_type_abort(subreq->async.private_data,
199 struct dcerpc_bh_raw_call_state *state =
201 struct dcerpc_bh_raw_call_state);
205 state->out_flags = 0;
206 if (subreq->flags & DCERPC_PULL_BIGENDIAN) {
207 state->out_flags |= LIBNDR_FLAG_BIGENDIAN;
210 fault_code = subreq->fault_code;
212 status = dcerpc_request_recv(subreq, state, &state->out_data);
213 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
214 status = dcerpc_fault_to_nt_status(fault_code);
216 if (!NT_STATUS_IS_OK(status)) {
217 tevent_req_nterror(req, status);
221 tevent_req_done(req);
224 static NTSTATUS dcerpc_bh_raw_call_recv(struct tevent_req *req,
230 struct dcerpc_bh_raw_call_state *state =
232 struct dcerpc_bh_raw_call_state);
235 if (tevent_req_is_nterror(req, &status)) {
236 tevent_req_received(req);
240 *out_data = talloc_move(mem_ctx, &state->out_data.data);
241 *out_length = state->out_data.length;
242 *out_flags = state->out_flags;
243 tevent_req_received(req);
247 struct dcerpc_bh_disconnect_state {
251 static struct tevent_req *dcerpc_bh_disconnect_send(TALLOC_CTX *mem_ctx,
252 struct tevent_context *ev,
253 struct dcerpc_binding_handle *h)
255 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
256 struct dcerpc_bh_state);
257 struct tevent_req *req;
258 struct dcerpc_bh_disconnect_state *state;
261 req = tevent_req_create(mem_ctx, &state,
262 struct dcerpc_bh_disconnect_state);
267 ok = dcerpc_bh_is_connected(h);
269 tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
270 return tevent_req_post(req, ev);
273 /* TODO: do a real disconnect ... */
276 tevent_req_done(req);
277 return tevent_req_post(req, ev);
280 static NTSTATUS dcerpc_bh_disconnect_recv(struct tevent_req *req)
284 if (tevent_req_is_nterror(req, &status)) {
285 tevent_req_received(req);
289 tevent_req_received(req);
293 static bool dcerpc_bh_push_bigendian(struct dcerpc_binding_handle *h)
295 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
296 struct dcerpc_bh_state);
298 if (hs->p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
305 static bool dcerpc_bh_ref_alloc(struct dcerpc_binding_handle *h)
307 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
308 struct dcerpc_bh_state);
310 if (hs->p->conn->flags & DCERPC_NDR_REF_ALLOC) {
317 static bool dcerpc_bh_use_ndr64(struct dcerpc_binding_handle *h)
319 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
320 struct dcerpc_bh_state);
322 if (hs->p->conn->flags & DCERPC_NDR64) {
329 static void dcerpc_bh_do_ndr_print(struct dcerpc_binding_handle *h,
331 const void *_struct_ptr,
332 const struct ndr_interface_call *call)
334 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
335 struct dcerpc_bh_state);
336 void *struct_ptr = discard_const(_struct_ptr);
338 if (ndr_flags & NDR_IN) {
339 if (hs->p->conn->flags & DCERPC_DEBUG_PRINT_IN) {
340 ndr_print_function_debug(call->ndr_print,
346 if (ndr_flags & NDR_OUT) {
347 if (hs->p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
348 ndr_print_function_debug(call->ndr_print,
356 static void dcerpc_bh_ndr_push_failed(struct dcerpc_binding_handle *h,
358 const void *struct_ptr,
359 const struct ndr_interface_call *call)
361 DEBUG(2,("Unable to ndr_push structure for %s - %s\n",
362 call->name, nt_errstr(error)));
365 static void dcerpc_bh_ndr_pull_failed(struct dcerpc_binding_handle *h,
367 const DATA_BLOB *blob,
368 const struct ndr_interface_call *call)
370 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
371 struct dcerpc_bh_state);
372 const uint32_t num_examples = 20;
375 DEBUG(2,("Unable to ndr_pull structure for %s - %s\n",
376 call->name, nt_errstr(error)));
378 if (hs->p->conn->packet_log_dir == NULL) return;
380 for (i=0;i<num_examples;i++) {
382 asprintf(&name, "%s/rpclog/%s-out.%d",
383 hs->p->conn->packet_log_dir,
388 if (!file_exist(name)) {
389 if (file_save(name, blob->data, blob->length)) {
390 DEBUG(10,("Logged rpc packet to %s\n", name));
399 static NTSTATUS dcerpc_bh_ndr_validate_in(struct dcerpc_binding_handle *h,
401 const DATA_BLOB *blob,
402 const struct ndr_interface_call *call)
404 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
405 struct dcerpc_bh_state);
407 if (hs->p->conn->flags & DCERPC_DEBUG_VALIDATE_IN) {
410 status = dcerpc_ndr_validate_in(hs->p->conn,
416 if (!NT_STATUS_IS_OK(status)) {
417 DEBUG(0,("Validation [in] failed for %s - %s\n",
418 call->name, nt_errstr(status)));
423 DEBUG(10,("rpc request data:\n"));
424 dump_data(10, blob->data, blob->length);
429 static NTSTATUS dcerpc_bh_ndr_validate_out(struct dcerpc_binding_handle *h,
430 struct ndr_pull *pull_in,
431 const void *_struct_ptr,
432 const struct ndr_interface_call *call)
434 struct dcerpc_bh_state *hs = dcerpc_binding_handle_data(h,
435 struct dcerpc_bh_state);
436 void *struct_ptr = discard_const(_struct_ptr);
438 DEBUG(10,("rpc reply data:\n"));
439 dump_data(10, pull_in->data, pull_in->data_size);
441 if (pull_in->offset != pull_in->data_size) {
442 DEBUG(0,("Warning! ignoring %u unread bytes at ofs:%u (0x%08X) for %s!\n",
443 pull_in->data_size - pull_in->offset,
444 pull_in->offset, pull_in->offset,
446 /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here,
447 but it turns out that early versions of NT
448 (specifically NT3.1) add junk onto the end of rpc
449 packets, so if we want to interoperate at all with
450 those versions then we need to ignore this error */
453 if (hs->p->conn->flags & DCERPC_DEBUG_VALIDATE_OUT) {
456 status = dcerpc_ndr_validate_out(hs->p->conn,
463 if (!NT_STATUS_IS_OK(status)) {
464 DEBUG(2,("Validation [out] failed for %s - %s\n",
465 call->name, nt_errstr(status)));
473 static const struct dcerpc_binding_handle_ops dcerpc_bh_ops = {
475 .is_connected = dcerpc_bh_is_connected,
476 .set_timeout = dcerpc_bh_set_timeout,
477 .raw_call_send = dcerpc_bh_raw_call_send,
478 .raw_call_recv = dcerpc_bh_raw_call_recv,
479 .disconnect_send = dcerpc_bh_disconnect_send,
480 .disconnect_recv = dcerpc_bh_disconnect_recv,
482 .push_bigendian = dcerpc_bh_push_bigendian,
483 .ref_alloc = dcerpc_bh_ref_alloc,
484 .use_ndr64 = dcerpc_bh_use_ndr64,
485 .do_ndr_print = dcerpc_bh_do_ndr_print,
486 .ndr_push_failed = dcerpc_bh_ndr_push_failed,
487 .ndr_pull_failed = dcerpc_bh_ndr_pull_failed,
488 .ndr_validate_in = dcerpc_bh_ndr_validate_in,
489 .ndr_validate_out = dcerpc_bh_ndr_validate_out,
492 /* initialise a dcerpc pipe. */
493 struct dcerpc_binding_handle *dcerpc_pipe_binding_handle(struct dcerpc_pipe *p)
495 struct dcerpc_binding_handle *h;
496 struct dcerpc_bh_state *hs;
498 h = dcerpc_binding_handle_create(p,
503 struct dcerpc_bh_state,
510 dcerpc_binding_handle_set_sync_ev(h, p->conn->event_ctx);
515 /* initialise a dcerpc pipe. */
516 _PUBLIC_ struct dcerpc_pipe *dcerpc_pipe_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev)
518 struct dcerpc_pipe *p;
520 p = talloc(mem_ctx, struct dcerpc_pipe);
525 p->conn = dcerpc_connection_init(p, ev);
526 if (p->conn == NULL) {
531 p->last_fault_code = 0;
533 p->request_timeout = DCERPC_REQUEST_TIMEOUT;
536 ZERO_STRUCT(p->syntax);
537 ZERO_STRUCT(p->transfer_syntax);
540 p->conn->flags |= DCERPC_DEBUG_PRINT_BOTH;
543 p->binding_handle = dcerpc_pipe_binding_handle(p);
544 if (p->binding_handle == NULL) {
554 choose the next call id to use
556 static uint32_t next_call_id(struct dcerpc_connection *c)
559 if (c->call_id == 0) {
566 setup for a ndr pull, also setting up any flags from the binding string
568 static struct ndr_pull *ndr_pull_init_flags(struct dcerpc_connection *c,
569 DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
571 struct ndr_pull *ndr = ndr_pull_init_blob(blob, mem_ctx);
573 if (ndr == NULL) return ndr;
575 if (c->flags & DCERPC_DEBUG_PAD_CHECK) {
576 ndr->flags |= LIBNDR_FLAG_PAD_CHECK;
579 if (c->flags & DCERPC_NDR_REF_ALLOC) {
580 ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
583 if (c->flags & DCERPC_NDR64) {
584 ndr->flags |= LIBNDR_FLAG_NDR64;
591 parse a data blob into a ncacn_packet structure. This handles both
592 input and output packets
594 static NTSTATUS ncacn_pull(struct dcerpc_connection *c, DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
595 struct ncacn_packet *pkt)
597 struct ndr_pull *ndr;
598 enum ndr_err_code ndr_err;
600 ndr = ndr_pull_init_flags(c, blob, mem_ctx);
602 return NT_STATUS_NO_MEMORY;
605 if (! (CVAL(blob->data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) {
606 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
609 ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
610 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
611 return ndr_map_error2ntstatus(ndr_err);
618 parse the authentication information on a dcerpc response packet
620 static NTSTATUS ncacn_pull_request_auth(struct dcerpc_connection *c, TALLOC_CTX *mem_ctx,
621 DATA_BLOB *raw_packet,
622 struct ncacn_packet *pkt)
625 struct dcerpc_auth auth;
626 uint32_t auth_length;
628 if (!c->security_state.auth_info ||
629 !c->security_state.generic_state) {
633 switch (c->security_state.auth_info->auth_level) {
634 case DCERPC_AUTH_LEVEL_PRIVACY:
635 case DCERPC_AUTH_LEVEL_INTEGRITY:
638 case DCERPC_AUTH_LEVEL_CONNECT:
639 if (pkt->auth_length != 0) {
643 case DCERPC_AUTH_LEVEL_NONE:
644 if (pkt->auth_length != 0) {
645 return NT_STATUS_INVALID_NETWORK_RESPONSE;
650 return NT_STATUS_INVALID_LEVEL;
653 status = dcerpc_pull_auth_trailer(pkt, mem_ctx,
654 &pkt->u.response.stub_and_verifier,
655 &auth, &auth_length, false);
656 NT_STATUS_NOT_OK_RETURN(status);
658 pkt->u.response.stub_and_verifier.length -= auth_length;
660 /* check signature or unseal the packet */
661 switch (c->security_state.auth_info->auth_level) {
662 case DCERPC_AUTH_LEVEL_PRIVACY:
663 status = gensec_unseal_packet(c->security_state.generic_state,
665 raw_packet->data + DCERPC_REQUEST_LENGTH,
666 pkt->u.response.stub_and_verifier.length,
668 raw_packet->length - auth.credentials.length,
670 memcpy(pkt->u.response.stub_and_verifier.data,
671 raw_packet->data + DCERPC_REQUEST_LENGTH,
672 pkt->u.response.stub_and_verifier.length);
675 case DCERPC_AUTH_LEVEL_INTEGRITY:
676 status = gensec_check_packet(c->security_state.generic_state,
678 pkt->u.response.stub_and_verifier.data,
679 pkt->u.response.stub_and_verifier.length,
681 raw_packet->length - auth.credentials.length,
685 case DCERPC_AUTH_LEVEL_CONNECT:
686 /* for now we ignore possible signatures here */
687 status = NT_STATUS_OK;
691 status = NT_STATUS_INVALID_LEVEL;
695 /* remove the indicated amount of padding */
696 if (pkt->u.response.stub_and_verifier.length < auth.auth_pad_length) {
697 return NT_STATUS_INFO_LENGTH_MISMATCH;
699 pkt->u.response.stub_and_verifier.length -= auth.auth_pad_length;
706 push a dcerpc request packet into a blob, possibly signing it.
708 static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c,
709 DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
711 struct ncacn_packet *pkt)
714 struct ndr_push *ndr;
716 size_t payload_length;
717 enum ndr_err_code ndr_err;
718 size_t hdr_size = DCERPC_REQUEST_LENGTH;
720 /* non-signed packets are simpler */
722 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
725 switch (c->security_state.auth_info->auth_level) {
726 case DCERPC_AUTH_LEVEL_PRIVACY:
727 case DCERPC_AUTH_LEVEL_INTEGRITY:
730 case DCERPC_AUTH_LEVEL_CONNECT:
731 /* TODO: let the gensec mech decide if it wants to generate a signature */
732 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
734 case DCERPC_AUTH_LEVEL_NONE:
735 return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
738 return NT_STATUS_INVALID_LEVEL;
741 ndr = ndr_push_init_ctx(mem_ctx);
743 return NT_STATUS_NO_MEMORY;
746 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
747 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
750 if (c->flags & DCERPC_NDR64) {
751 ndr->flags |= LIBNDR_FLAG_NDR64;
754 if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
755 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
759 ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
760 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
761 return ndr_map_error2ntstatus(ndr_err);
764 /* pad to 16 byte multiple in the payload portion of the
765 packet. This matches what w2k3 does. Note that we can't use
766 ndr_push_align() as that is relative to the start of the
767 whole packet, whereas w2k8 wants it relative to the start
769 c->security_state.auth_info->auth_pad_length =
770 (16 - (pkt->u.request.stub_and_verifier.length & 15)) & 15;
771 ndr_err = ndr_push_zero(ndr, c->security_state.auth_info->auth_pad_length);
772 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
773 return ndr_map_error2ntstatus(ndr_err);
776 payload_length = pkt->u.request.stub_and_verifier.length +
777 c->security_state.auth_info->auth_pad_length;
779 /* we start without signature, it will appended later */
780 c->security_state.auth_info->credentials = data_blob(NULL,0);
782 /* add the auth verifier */
783 ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, c->security_state.auth_info);
784 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
785 return ndr_map_error2ntstatus(ndr_err);
788 /* extract the whole packet as a blob */
789 *blob = ndr_push_blob(ndr);
792 * Setup the frag and auth length in the packet buffer.
793 * This is needed if the GENSEC mech does AEAD signing
794 * of the packet headers. The signature itself will be
797 dcerpc_set_frag_length(blob, blob->length + sig_size);
798 dcerpc_set_auth_length(blob, sig_size);
800 /* sign or seal the packet */
801 switch (c->security_state.auth_info->auth_level) {
802 case DCERPC_AUTH_LEVEL_PRIVACY:
803 status = gensec_seal_packet(c->security_state.generic_state,
805 blob->data + hdr_size,
810 if (!NT_STATUS_IS_OK(status)) {
815 case DCERPC_AUTH_LEVEL_INTEGRITY:
816 status = gensec_sign_packet(c->security_state.generic_state,
818 blob->data + hdr_size,
823 if (!NT_STATUS_IS_OK(status)) {
829 status = NT_STATUS_INVALID_LEVEL;
833 if (creds2.length != sig_size) {
834 /* this means the sig_size estimate for the signature
835 was incorrect. We have to correct the packet
836 sizes. That means we could go over the max fragment
838 DEBUG(3,("ncacn_push_request_sign: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n",
839 (unsigned) creds2.length,
841 (unsigned) c->security_state.auth_info->auth_pad_length,
842 (unsigned) pkt->u.request.stub_and_verifier.length));
843 dcerpc_set_frag_length(blob, blob->length + creds2.length);
844 dcerpc_set_auth_length(blob, creds2.length);
847 if (!data_blob_append(mem_ctx, blob, creds2.data, creds2.length)) {
848 return NT_STATUS_NO_MEMORY;
856 fill in the fixed values in a dcerpc header
858 static void init_ncacn_hdr(struct dcerpc_connection *c, struct ncacn_packet *pkt)
861 pkt->rpc_vers_minor = 0;
862 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
865 pkt->drep[0] = DCERPC_DREP_LE;
873 map a bind nak reason to a NTSTATUS
875 static NTSTATUS dcerpc_map_reason(uint16_t reason)
878 case DCERPC_BIND_REASON_ASYNTAX:
879 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
880 case DCERPC_BIND_REASON_INVALID_AUTH_TYPE:
881 return NT_STATUS_INVALID_PARAMETER;
883 return NT_STATUS_UNSUCCESSFUL;
887 a bind or alter context has failed
889 static void dcerpc_composite_fail(struct rpc_request *req)
891 struct composite_context *c = talloc_get_type(req->async.private_data,
892 struct composite_context);
893 composite_error(c, req->status);
897 remove requests from the pending or queued queues
899 static int dcerpc_req_dequeue(struct rpc_request *req)
901 switch (req->state) {
902 case RPC_REQUEST_QUEUED:
903 DLIST_REMOVE(req->p->conn->request_queue, req);
905 case RPC_REQUEST_PENDING:
906 DLIST_REMOVE(req->p->conn->pending, req);
908 case RPC_REQUEST_DONE:
916 mark the dcerpc connection dead. All outstanding requests get an error
918 static void dcerpc_connection_dead(struct dcerpc_connection *conn, NTSTATUS status)
920 if (conn->dead) return;
924 if (conn->transport.shutdown_pipe) {
925 conn->transport.shutdown_pipe(conn, status);
928 /* all pending requests get the error */
929 while (conn->pending) {
930 struct rpc_request *req = conn->pending;
931 dcerpc_req_dequeue(req);
932 req->state = RPC_REQUEST_DONE;
933 req->status = status;
934 if (req->async.callback) {
935 req->async.callback(req);
939 talloc_set_destructor(conn, NULL);
940 if (conn->free_skipped) {
946 forward declarations of the recv_data handlers for the types of
947 packets we need to handle
949 static void dcerpc_request_recv_data(struct dcerpc_connection *c,
950 DATA_BLOB *raw_packet, struct ncacn_packet *pkt);
953 receive a dcerpc reply from the transport. Here we work out what
954 type of reply it is (normal request, bind or alter context) and
955 dispatch to the appropriate handler
957 static void dcerpc_recv_data(struct dcerpc_connection *conn, DATA_BLOB *blob, NTSTATUS status)
959 struct ncacn_packet pkt;
961 if (NT_STATUS_IS_OK(status) && blob->length == 0) {
962 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
965 /* the transport may be telling us of a severe error, such as
967 if (!NT_STATUS_IS_OK(status)) {
968 data_blob_free(blob);
969 dcerpc_connection_dead(conn, status);
973 /* parse the basic packet to work out what type of response this is */
974 status = ncacn_pull(conn, blob, blob->data, &pkt);
975 if (!NT_STATUS_IS_OK(status)) {
976 data_blob_free(blob);
977 dcerpc_connection_dead(conn, status);
980 dcerpc_request_recv_data(conn, blob, &pkt);
984 Receive a bind reply from the transport
986 static void dcerpc_bind_recv_handler(struct rpc_request *req,
987 DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
989 struct composite_context *c;
990 struct dcerpc_connection *conn;
992 c = talloc_get_type(req->async.private_data, struct composite_context);
994 if (pkt->ptype == DCERPC_PKT_BIND_NAK) {
995 DEBUG(2,("dcerpc: bind_nak reason %d\n",
996 pkt->u.bind_nak.reject_reason));
997 composite_error(c, dcerpc_map_reason(pkt->u.bind_nak.
1002 if ((pkt->ptype != DCERPC_PKT_BIND_ACK) ||
1003 (pkt->u.bind_ack.num_results == 0) ||
1004 (pkt->u.bind_ack.ctx_list[0].result != 0)) {
1005 req->p->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
1006 composite_error(c, NT_STATUS_NET_WRITE_FAULT);
1010 conn = req->p->conn;
1012 conn->srv_max_xmit_frag = pkt->u.bind_ack.max_xmit_frag;
1013 conn->srv_max_recv_frag = pkt->u.bind_ack.max_recv_frag;
1015 if ((req->p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) &&
1016 (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX)) {
1017 conn->flags |= DCERPC_CONCURRENT_MULTIPLEX;
1020 if ((req->p->binding->flags & DCERPC_HEADER_SIGNING) &&
1021 (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
1022 conn->flags |= DCERPC_HEADER_SIGNING;
1025 /* the bind_ack might contain a reply set of credentials */
1026 if (conn->security_state.auth_info && pkt->u.bind_ack.auth_info.length) {
1028 uint32_t auth_length;
1029 status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.bind_ack.auth_info,
1030 conn->security_state.auth_info, &auth_length, true);
1031 if (!NT_STATUS_IS_OK(status)) {
1032 composite_error(c, status);
1037 req->p->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
1043 handle timeouts of individual dcerpc requests
1045 static void dcerpc_timeout_handler(struct tevent_context *ev, struct tevent_timer *te,
1046 struct timeval t, void *private_data)
1048 struct rpc_request *req = talloc_get_type(private_data, struct rpc_request);
1050 if (req->ignore_timeout) {
1051 dcerpc_req_dequeue(req);
1052 req->state = RPC_REQUEST_DONE;
1053 req->status = NT_STATUS_IO_TIMEOUT;
1054 if (req->async.callback) {
1055 req->async.callback(req);
1060 dcerpc_connection_dead(req->p->conn, NT_STATUS_IO_TIMEOUT);
1064 send a async dcerpc bind request
1066 struct composite_context *dcerpc_bind_send(struct dcerpc_pipe *p,
1067 TALLOC_CTX *mem_ctx,
1068 const struct ndr_syntax_id *syntax,
1069 const struct ndr_syntax_id *transfer_syntax)
1071 struct composite_context *c;
1072 struct ncacn_packet pkt;
1074 struct rpc_request *req;
1076 c = composite_create(mem_ctx,p->conn->event_ctx);
1077 if (c == NULL) return NULL;
1079 c->private_data = p;
1081 p->syntax = *syntax;
1082 p->transfer_syntax = *transfer_syntax;
1084 init_ncacn_hdr(p->conn, &pkt);
1086 pkt.ptype = DCERPC_PKT_BIND;
1087 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1088 pkt.call_id = p->conn->call_id;
1089 pkt.auth_length = 0;
1091 if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {
1092 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1095 if (p->binding->flags & DCERPC_HEADER_SIGNING) {
1096 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1099 pkt.u.bind.max_xmit_frag = 5840;
1100 pkt.u.bind.max_recv_frag = 5840;
1101 pkt.u.bind.assoc_group_id = p->binding->assoc_group_id;
1102 pkt.u.bind.num_contexts = 1;
1103 pkt.u.bind.ctx_list = talloc_array(mem_ctx, struct dcerpc_ctx_list, 1);
1104 if (composite_nomem(pkt.u.bind.ctx_list, c)) return c;
1105 pkt.u.bind.ctx_list[0].context_id = p->context_id;
1106 pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1;
1107 pkt.u.bind.ctx_list[0].abstract_syntax = p->syntax;
1108 pkt.u.bind.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
1109 pkt.u.bind.auth_info = data_blob(NULL, 0);
1111 /* construct the NDR form of the packet */
1112 c->status = ncacn_push_auth(&blob, c, &pkt,
1113 p->conn->security_state.auth_info);
1114 if (!composite_is_ok(c)) return c;
1116 p->conn->transport.recv_data = dcerpc_recv_data;
1119 * we allocate a dcerpc_request so we can be in the same
1120 * request queue as normal requests
1122 req = talloc_zero(c, struct rpc_request);
1123 if (composite_nomem(req, c)) return c;
1125 req->state = RPC_REQUEST_PENDING;
1126 req->call_id = pkt.call_id;
1127 req->async.private_data = c;
1128 req->async.callback = dcerpc_composite_fail;
1130 req->recv_handler = dcerpc_bind_recv_handler;
1131 DLIST_ADD_END(p->conn->pending, req, struct rpc_request *);
1132 talloc_set_destructor(req, dcerpc_req_dequeue);
1134 c->status = p->conn->transport.send_request(p->conn, &blob,
1136 if (!composite_is_ok(c)) return c;
1138 event_add_timed(c->event_ctx, req,
1139 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
1140 dcerpc_timeout_handler, req);
1146 recv side of async dcerpc bind request
1148 NTSTATUS dcerpc_bind_recv(struct composite_context *ctx)
1150 NTSTATUS result = composite_wait(ctx);
1156 perform a continued bind (and auth3)
1158 NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p,
1159 TALLOC_CTX *mem_ctx)
1161 struct ncacn_packet pkt;
1165 init_ncacn_hdr(p->conn, &pkt);
1167 pkt.ptype = DCERPC_PKT_AUTH3;
1168 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1169 pkt.call_id = next_call_id(p->conn);
1170 pkt.auth_length = 0;
1171 pkt.u.auth3.auth_info = data_blob(NULL, 0);
1173 if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {
1174 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
1177 if (p->binding->flags & DCERPC_HEADER_SIGNING) {
1178 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1181 /* construct the NDR form of the packet */
1182 status = ncacn_push_auth(&blob, mem_ctx,
1184 p->conn->security_state.auth_info);
1185 if (!NT_STATUS_IS_OK(status)) {
1189 /* send it on its way */
1190 status = p->conn->transport.send_request(p->conn, &blob, false);
1191 if (!NT_STATUS_IS_OK(status)) {
1195 return NT_STATUS_OK;
1200 process a fragment received from the transport layer during a
1203 This function frees the data
1205 static void dcerpc_request_recv_data(struct dcerpc_connection *c,
1206 DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
1208 struct rpc_request *req;
1209 unsigned int length;
1210 NTSTATUS status = NT_STATUS_OK;
1213 if this is an authenticated connection then parse and check
1214 the auth info. We have to do this before finding the
1215 matching packet, as the request structure might have been
1216 removed due to a timeout, but if it has been we still need
1217 to run the auth routines so that we don't get the sign/seal
1218 info out of step with the server
1220 if (c->security_state.auth_info && c->security_state.generic_state &&
1221 pkt->ptype == DCERPC_PKT_RESPONSE) {
1222 status = ncacn_pull_request_auth(c, raw_packet->data, raw_packet, pkt);
1225 /* find the matching request */
1226 for (req=c->pending;req;req=req->next) {
1227 if (pkt->call_id == req->call_id) break;
1231 /* useful for testing certain vendors RPC servers */
1232 if (req == NULL && c->pending && pkt->call_id == 0) {
1233 DEBUG(0,("HACK FOR INCORRECT CALL ID\n"));
1239 DEBUG(2,("dcerpc_request: unmatched call_id %u in response packet\n", pkt->call_id));
1240 data_blob_free(raw_packet);
1244 talloc_steal(req, raw_packet->data);
1246 if (req->recv_handler != NULL) {
1247 dcerpc_req_dequeue(req);
1248 req->state = RPC_REQUEST_DONE;
1249 req->recv_handler(req, raw_packet, pkt);
1253 if (pkt->ptype == DCERPC_PKT_FAULT) {
1254 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
1255 req->fault_code = pkt->u.fault.status;
1256 req->status = NT_STATUS_NET_WRITE_FAULT;
1260 if (pkt->ptype != DCERPC_PKT_RESPONSE) {
1261 DEBUG(2,("Unexpected packet type %d in dcerpc response\n",
1263 req->fault_code = DCERPC_FAULT_OTHER;
1264 req->status = NT_STATUS_NET_WRITE_FAULT;
1268 /* now check the status from the auth routines, and if it failed then fail
1269 this request accordingly */
1270 if (!NT_STATUS_IS_OK(status)) {
1271 req->status = status;
1275 length = pkt->u.response.stub_and_verifier.length;
1278 req->payload.data = talloc_realloc(req,
1281 req->payload.length + length);
1282 if (!req->payload.data) {
1283 req->status = NT_STATUS_NO_MEMORY;
1286 memcpy(req->payload.data+req->payload.length,
1287 pkt->u.response.stub_and_verifier.data, length);
1288 req->payload.length += length;
1291 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1292 c->transport.send_read(c);
1296 if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
1297 req->flags |= DCERPC_PULL_BIGENDIAN;
1299 req->flags &= ~DCERPC_PULL_BIGENDIAN;
1304 /* we've got the full payload */
1305 req->state = RPC_REQUEST_DONE;
1306 DLIST_REMOVE(c->pending, req);
1308 if (c->request_queue != NULL) {
1309 /* We have to look at shipping further requests before calling
1310 * the async function, that one might close the pipe */
1311 dcerpc_ship_next_request(c);
1314 if (req->async.callback) {
1315 req->async.callback(req);
1320 perform the send side of a async dcerpc request
1322 static struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p,
1323 const struct GUID *object,
1325 DATA_BLOB *stub_data)
1327 struct rpc_request *req;
1329 p->conn->transport.recv_data = dcerpc_recv_data;
1331 req = talloc(p, struct rpc_request);
1337 req->call_id = next_call_id(p->conn);
1338 req->status = NT_STATUS_OK;
1339 req->state = RPC_REQUEST_QUEUED;
1340 req->payload = data_blob(NULL, 0);
1342 req->fault_code = 0;
1343 req->ignore_timeout = false;
1344 req->async.callback = NULL;
1345 req->async.private_data = NULL;
1346 req->recv_handler = NULL;
1348 if (object != NULL) {
1349 req->object = (struct GUID *)talloc_memdup(req, (const void *)object, sizeof(*object));
1350 if (req->object == NULL) {
1359 req->request_data.length = stub_data->length;
1360 req->request_data.data = talloc_reference(req, stub_data->data);
1361 if (req->request_data.length && req->request_data.data == NULL) {
1365 DLIST_ADD_END(p->conn->request_queue, req, struct rpc_request *);
1366 talloc_set_destructor(req, dcerpc_req_dequeue);
1368 dcerpc_ship_next_request(p->conn);
1370 if (p->request_timeout) {
1371 event_add_timed(dcerpc_event_context(p), req,
1372 timeval_current_ofs(p->request_timeout, 0),
1373 dcerpc_timeout_handler, req);
1380 Send a request using the transport
1383 static void dcerpc_ship_next_request(struct dcerpc_connection *c)
1385 struct rpc_request *req;
1386 struct dcerpc_pipe *p;
1387 DATA_BLOB *stub_data;
1388 struct ncacn_packet pkt;
1390 uint32_t remaining, chunk_size;
1391 bool first_packet = true;
1392 size_t sig_size = 0;
1393 bool need_async = false;
1395 req = c->request_queue;
1401 stub_data = &req->request_data;
1407 DLIST_REMOVE(c->request_queue, req);
1408 DLIST_ADD(c->pending, req);
1409 req->state = RPC_REQUEST_PENDING;
1411 init_ncacn_hdr(p->conn, &pkt);
1413 remaining = stub_data->length;
1415 /* we can write a full max_recv_frag size, minus the dcerpc
1416 request header size */
1417 chunk_size = p->conn->srv_max_recv_frag;
1418 chunk_size -= DCERPC_REQUEST_LENGTH;
1419 if (c->security_state.auth_info &&
1420 c->security_state.generic_state) {
1421 sig_size = gensec_sig_size(c->security_state.generic_state,
1422 p->conn->srv_max_recv_frag);
1424 chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
1425 chunk_size -= sig_size;
1428 chunk_size -= (chunk_size % 16);
1430 pkt.ptype = DCERPC_PKT_REQUEST;
1431 pkt.call_id = req->call_id;
1432 pkt.auth_length = 0;
1434 pkt.u.request.alloc_hint = remaining;
1435 pkt.u.request.context_id = p->context_id;
1436 pkt.u.request.opnum = req->opnum;
1439 pkt.u.request.object.object = *req->object;
1440 pkt.pfc_flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1441 chunk_size -= ndr_size_GUID(req->object,0);
1444 /* we send a series of pdus without waiting for a reply */
1445 while (remaining > 0 || first_packet) {
1446 uint32_t chunk = MIN(chunk_size, remaining);
1447 bool last_frag = false;
1448 bool do_trans = false;
1450 first_packet = false;
1451 pkt.pfc_flags &= ~(DCERPC_PFC_FLAG_FIRST |DCERPC_PFC_FLAG_LAST);
1453 if (remaining == stub_data->length) {
1454 pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST;
1456 if (chunk == remaining) {
1457 pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
1461 pkt.u.request.stub_and_verifier.data = stub_data->data +
1462 (stub_data->length - remaining);
1463 pkt.u.request.stub_and_verifier.length = chunk;
1465 req->status = ncacn_push_request_sign(p->conn, &blob, req, sig_size, &pkt);
1466 if (!NT_STATUS_IS_OK(req->status)) {
1467 req->state = RPC_REQUEST_DONE;
1468 DLIST_REMOVE(p->conn->pending, req);
1472 if (last_frag && !need_async) {
1476 req->status = p->conn->transport.send_request(p->conn, &blob, do_trans);
1477 if (!NT_STATUS_IS_OK(req->status)) {
1478 req->state = RPC_REQUEST_DONE;
1479 DLIST_REMOVE(p->conn->pending, req);
1483 if (last_frag && !do_trans) {
1484 req->status = p->conn->transport.send_read(p->conn);
1485 if (!NT_STATUS_IS_OK(req->status)) {
1486 req->state = RPC_REQUEST_DONE;
1487 DLIST_REMOVE(p->conn->pending, req);
1497 return the event context for a dcerpc pipe
1498 used by callers who wish to operate asynchronously
1500 _PUBLIC_ struct tevent_context *dcerpc_event_context(struct dcerpc_pipe *p)
1502 return p->conn->event_ctx;
1508 perform the receive side of a async dcerpc request
1510 NTSTATUS dcerpc_request_recv(struct rpc_request *req,
1511 TALLOC_CTX *mem_ctx,
1512 DATA_BLOB *stub_data)
1516 while (req->state != RPC_REQUEST_DONE) {
1517 struct tevent_context *ctx = dcerpc_event_context(req->p);
1518 if (event_loop_once(ctx) != 0) {
1519 return NT_STATUS_CONNECTION_DISCONNECTED;
1522 *stub_data = req->payload;
1523 status = req->status;
1524 if (stub_data->data) {
1525 stub_data->data = talloc_steal(mem_ctx, stub_data->data);
1527 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
1528 req->p->last_fault_code = req->fault_code;
1530 talloc_unlink(talloc_parent(req), req);
1535 perform a full request/response pair on a dcerpc pipe
1537 NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
1538 struct GUID *object,
1540 TALLOC_CTX *mem_ctx,
1541 DATA_BLOB *stub_data_in,
1542 DATA_BLOB *stub_data_out)
1544 struct rpc_request *req;
1546 req = dcerpc_request_send(p, object, opnum, stub_data_in);
1548 return NT_STATUS_NO_MEMORY;
1551 return dcerpc_request_recv(req, mem_ctx, stub_data_out);
1556 this is a paranoid NDR validator. For every packet we push onto the wire
1557 we pull it back again, then push it again. Then we compare the raw NDR data
1558 for that to the NDR we initially generated. If they don't match then we know
1559 we must have a bug in either the pull or push side of our code
1561 static NTSTATUS dcerpc_ndr_validate_in(struct dcerpc_connection *c,
1562 TALLOC_CTX *mem_ctx,
1565 ndr_push_flags_fn_t ndr_push,
1566 ndr_pull_flags_fn_t ndr_pull)
1569 struct ndr_pull *pull;
1570 struct ndr_push *push;
1572 enum ndr_err_code ndr_err;
1574 st = talloc_size(mem_ctx, struct_size);
1576 return NT_STATUS_NO_MEMORY;
1579 pull = ndr_pull_init_flags(c, &blob, mem_ctx);
1581 return NT_STATUS_NO_MEMORY;
1583 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1585 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
1586 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1589 if (c->flags & DCERPC_NDR64) {
1590 pull->flags |= LIBNDR_FLAG_NDR64;
1593 ndr_err = ndr_pull(pull, NDR_IN, st);
1594 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1595 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1596 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1597 "failed input validation pull - %s",
1599 return ndr_map_error2ntstatus(ndr_err);
1602 push = ndr_push_init_ctx(mem_ctx);
1604 return NT_STATUS_NO_MEMORY;
1607 if (c->flags & DCERPC_PUSH_BIGENDIAN) {
1608 push->flags |= LIBNDR_FLAG_BIGENDIAN;
1611 if (c->flags & DCERPC_NDR64) {
1612 push->flags |= LIBNDR_FLAG_NDR64;
1615 ndr_err = ndr_push(push, NDR_IN, st);
1616 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1617 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1618 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1619 "failed input validation push - %s",
1621 return ndr_map_error2ntstatus(ndr_err);
1624 blob2 = ndr_push_blob(push);
1626 if (data_blob_cmp(&blob, &blob2) != 0) {
1627 DEBUG(3,("original:\n"));
1628 dump_data(3, blob.data, blob.length);
1629 DEBUG(3,("secondary:\n"));
1630 dump_data(3, blob2.data, blob2.length);
1631 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1632 "failed input validation blobs doesn't match");
1633 return ndr_map_error2ntstatus(ndr_err);
1636 return NT_STATUS_OK;
1640 this is a paranoid NDR input validator. For every packet we pull
1641 from the wire we push it back again then pull and push it
1642 again. Then we compare the raw NDR data for that to the NDR we
1643 initially generated. If they don't match then we know we must have a
1644 bug in either the pull or push side of our code
1646 static NTSTATUS dcerpc_ndr_validate_out(struct dcerpc_connection *c,
1647 struct ndr_pull *pull_in,
1650 ndr_push_flags_fn_t ndr_push,
1651 ndr_pull_flags_fn_t ndr_pull,
1652 ndr_print_function_t ndr_print)
1655 struct ndr_pull *pull;
1656 struct ndr_push *push;
1657 DATA_BLOB blob, blob2;
1658 TALLOC_CTX *mem_ctx = pull_in;
1660 enum ndr_err_code ndr_err;
1662 st = talloc_size(mem_ctx, struct_size);
1664 return NT_STATUS_NO_MEMORY;
1666 memcpy(st, struct_ptr, struct_size);
1668 push = ndr_push_init_ctx(mem_ctx);
1670 return NT_STATUS_NO_MEMORY;
1673 ndr_err = ndr_push(push, NDR_OUT, struct_ptr);
1674 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1675 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1676 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1677 "failed output validation push - %s",
1679 return ndr_map_error2ntstatus(ndr_err);
1682 blob = ndr_push_blob(push);
1684 pull = ndr_pull_init_flags(c, &blob, mem_ctx);
1686 return NT_STATUS_NO_MEMORY;
1689 pull->flags |= LIBNDR_FLAG_REF_ALLOC;
1690 ndr_err = ndr_pull(pull, NDR_OUT, st);
1691 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1692 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1693 ndr_err = ndr_pull_error(pull, NDR_ERR_VALIDATE,
1694 "failed output validation pull - %s",
1696 return ndr_map_error2ntstatus(ndr_err);
1699 push = ndr_push_init_ctx(mem_ctx);
1701 return NT_STATUS_NO_MEMORY;
1704 ndr_err = ndr_push(push, NDR_OUT, st);
1705 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1706 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1707 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1708 "failed output validation push2 - %s",
1710 return ndr_map_error2ntstatus(ndr_err);
1713 blob2 = ndr_push_blob(push);
1715 if (data_blob_cmp(&blob, &blob2) != 0) {
1716 DEBUG(3,("original:\n"));
1717 dump_data(3, blob.data, blob.length);
1718 DEBUG(3,("secondary:\n"));
1719 dump_data(3, blob2.data, blob2.length);
1720 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1721 "failed output validation blobs doesn't match");
1722 return ndr_map_error2ntstatus(ndr_err);
1725 /* this checks the printed forms of the two structures, which effectively
1726 tests all of the value() attributes */
1727 s1 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE",
1728 NDR_OUT, struct_ptr);
1729 s2 = ndr_print_function_string(mem_ctx, ndr_print, "VALIDATE",
1731 if (strcmp(s1, s2) != 0) {
1733 DEBUG(3,("VALIDATE ERROR:\nWIRE:\n%s\n GEN:\n%s\n", s1, s2));
1735 /* this is sometimes useful */
1736 printf("VALIDATE ERROR\n");
1737 file_save("wire.dat", s1, strlen(s1));
1738 file_save("gen.dat", s2, strlen(s2));
1739 system("diff -u wire.dat gen.dat");
1741 ndr_err = ndr_push_error(push, NDR_ERR_VALIDATE,
1742 "failed output validation strings doesn't match");
1743 return ndr_map_error2ntstatus(ndr_err);
1746 return NT_STATUS_OK;
1751 send a rpc request given a dcerpc_call structure
1753 struct rpc_request *dcerpc_ndr_request_send(struct dcerpc_pipe *p,
1754 const struct GUID *object,
1755 const struct ndr_interface_table *table,
1758 TALLOC_CTX *mem_ctx,
1761 const struct ndr_interface_call *call;
1762 struct ndr_push *push;
1765 struct rpc_request *req;
1766 enum ndr_err_code ndr_err;
1768 call = &table->calls[opnum];
1770 /* setup for a ndr_push_* call */
1771 push = ndr_push_init_ctx(mem_ctx);
1776 if (p->conn->flags & DCERPC_PUSH_BIGENDIAN) {
1777 push->flags |= LIBNDR_FLAG_BIGENDIAN;
1780 if (p->conn->flags & DCERPC_NDR64) {
1781 push->flags |= LIBNDR_FLAG_NDR64;
1784 /* push the structure into a blob */
1785 ndr_err = call->ndr_push(push, NDR_IN, r);
1786 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1787 status = ndr_map_error2ntstatus(ndr_err);
1788 DEBUG(2,("Unable to ndr_push structure in dcerpc_ndr_request_send - %s\n",
1789 nt_errstr(status)));
1794 /* retrieve the blob */
1795 request = ndr_push_blob(push);
1797 if (p->conn->flags & DCERPC_DEBUG_VALIDATE_IN) {
1798 status = dcerpc_ndr_validate_in(p->conn, push, request, call->struct_size,
1799 call->ndr_push, call->ndr_pull);
1800 if (!NT_STATUS_IS_OK(status)) {
1801 DEBUG(2,("Validation failed in dcerpc_ndr_request_send - %s\n",
1802 nt_errstr(status)));
1808 DEBUG(10,("rpc request data:\n"));
1809 dump_data(10, request.data, request.length);
1811 /* make the actual dcerpc request */
1812 req = dcerpc_request_send(p, object, opnum, &request);
1815 req->ndr.table = table;
1816 req->ndr.opnum = opnum;
1817 req->ndr.struct_ptr = r;
1818 req->ndr.mem_ctx = mem_ctx;
1827 receive the answer from a dcerpc_ndr_request_send()
1829 _PUBLIC_ NTSTATUS dcerpc_ndr_request_recv(struct rpc_request *req)
1831 struct dcerpc_pipe *p = req->p;
1834 struct ndr_pull *pull;
1836 TALLOC_CTX *mem_ctx = req->ndr.mem_ctx;
1837 void *r = req->ndr.struct_ptr;
1838 uint32_t opnum = req->ndr.opnum;
1839 const struct ndr_interface_table *table = req->ndr.table;
1840 const struct ndr_interface_call *call = &table->calls[opnum];
1841 enum ndr_err_code ndr_err;
1843 /* make sure the recv code doesn't free the request, as we
1844 need to grab the flags element before it is freed */
1845 if (talloc_reference(p, req) == NULL) {
1846 return NT_STATUS_NO_MEMORY;
1849 status = dcerpc_request_recv(req, mem_ctx, &response);
1850 if (!NT_STATUS_IS_OK(status)) {
1851 talloc_unlink(p, req);
1857 /* prepare for ndr_pull_* */
1858 pull = ndr_pull_init_flags(p->conn, &response, mem_ctx);
1860 talloc_unlink(p, req);
1861 return NT_STATUS_NO_MEMORY;
1865 pull->data = talloc_steal(pull, pull->data);
1867 talloc_unlink(p, req);
1869 if (flags & DCERPC_PULL_BIGENDIAN) {
1870 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
1873 DEBUG(10,("rpc reply data:\n"));
1874 dump_data(10, pull->data, pull->data_size);
1876 /* pull the structure from the blob */
1877 ndr_err = call->ndr_pull(pull, NDR_OUT, r);
1878 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1879 status = ndr_map_error2ntstatus(ndr_err);
1880 dcerpc_log_packet(p->conn->packet_log_dir,
1881 table, opnum, NDR_OUT,
1886 if (p->conn->flags & DCERPC_DEBUG_VALIDATE_OUT) {
1887 status = dcerpc_ndr_validate_out(p->conn, pull, r, call->struct_size,
1888 call->ndr_push, call->ndr_pull,
1890 if (!NT_STATUS_IS_OK(status)) {
1891 dcerpc_log_packet(p->conn->packet_log_dir,
1892 table, opnum, NDR_OUT,
1898 if (pull->offset != pull->data_size) {
1899 DEBUG(0,("Warning! ignoring %d unread bytes in rpc packet!\n",
1900 pull->data_size - pull->offset));
1901 /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here,
1902 but it turns out that early versions of NT
1903 (specifically NT3.1) add junk onto the end of rpc
1904 packets, so if we want to interoperate at all with
1905 those versions then we need to ignore this error */
1908 /* TODO: make pull context independent from the output mem_ctx and free the pull context */
1910 return NT_STATUS_OK;
1915 a useful helper function for synchronous rpc requests
1917 this can be used when you have ndr push/pull functions in the
1920 _PUBLIC_ NTSTATUS dcerpc_ndr_request(struct dcerpc_pipe *p,
1921 const struct GUID *object,
1922 const struct ndr_interface_table *table,
1924 TALLOC_CTX *mem_ctx,
1927 struct rpc_request *req;
1929 req = dcerpc_ndr_request_send(p, object, table, opnum, false, mem_ctx, r);
1931 return NT_STATUS_NO_MEMORY;
1934 return dcerpc_ndr_request_recv(req);
1939 a useful function for retrieving the server name we connected to
1941 _PUBLIC_ const char *dcerpc_server_name(struct dcerpc_pipe *p)
1943 if (!p->conn->transport.target_hostname) {
1944 if (!p->conn->transport.peer_name) {
1947 return p->conn->transport.peer_name(p->conn);
1949 return p->conn->transport.target_hostname(p->conn);
1954 get the dcerpc auth_level for a open connection
1956 uint32_t dcerpc_auth_level(struct dcerpc_connection *c)
1960 if (c->flags & DCERPC_SEAL) {
1961 auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1962 } else if (c->flags & DCERPC_SIGN) {
1963 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1964 } else if (c->flags & DCERPC_CONNECT) {
1965 auth_level = DCERPC_AUTH_LEVEL_CONNECT;
1967 auth_level = DCERPC_AUTH_LEVEL_NONE;
1973 Receive an alter reply from the transport
1975 static void dcerpc_alter_recv_handler(struct rpc_request *req,
1976 DATA_BLOB *raw_packet, struct ncacn_packet *pkt)
1978 struct composite_context *c;
1979 struct dcerpc_pipe *recv_pipe;
1981 c = talloc_get_type(req->async.private_data, struct composite_context);
1982 recv_pipe = talloc_get_type(c->private_data, struct dcerpc_pipe);
1984 if (pkt->ptype == DCERPC_PKT_ALTER_RESP &&
1985 pkt->u.alter_resp.num_results == 1 &&
1986 pkt->u.alter_resp.ctx_list[0].result != 0) {
1987 DEBUG(2,("dcerpc: alter_resp failed - reason %d\n",
1988 pkt->u.alter_resp.ctx_list[0].reason));
1989 composite_error(c, dcerpc_map_reason(pkt->u.alter_resp.ctx_list[0].reason));
1993 if (pkt->ptype == DCERPC_PKT_FAULT) {
1994 DEBUG(5,("rpc fault: %s\n", dcerpc_errstr(c, pkt->u.fault.status)));
1995 recv_pipe->last_fault_code = pkt->u.fault.status;
1996 composite_error(c, NT_STATUS_NET_WRITE_FAULT);
2000 if (pkt->ptype != DCERPC_PKT_ALTER_RESP ||
2001 pkt->u.alter_resp.num_results == 0 ||
2002 pkt->u.alter_resp.ctx_list[0].result != 0) {
2003 recv_pipe->last_fault_code = DCERPC_NCA_S_PROTO_ERROR;
2004 composite_error(c, NT_STATUS_NET_WRITE_FAULT);
2008 /* the alter_resp might contain a reply set of credentials */
2009 if (recv_pipe->conn->security_state.auth_info &&
2010 pkt->u.alter_resp.auth_info.length) {
2011 struct dcerpc_connection *conn = recv_pipe->conn;
2013 uint32_t auth_length;
2014 status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.alter_resp.auth_info,
2015 conn->security_state.auth_info, &auth_length, true);
2016 if (!NT_STATUS_IS_OK(status)) {
2017 composite_error(c, status);
2026 send a dcerpc alter_context request
2028 struct composite_context *dcerpc_alter_context_send(struct dcerpc_pipe *p,
2029 TALLOC_CTX *mem_ctx,
2030 const struct ndr_syntax_id *syntax,
2031 const struct ndr_syntax_id *transfer_syntax)
2033 struct composite_context *c;
2034 struct ncacn_packet pkt;
2036 struct rpc_request *req;
2038 c = composite_create(mem_ctx, p->conn->event_ctx);
2039 if (c == NULL) return NULL;
2041 c->private_data = p;
2043 p->syntax = *syntax;
2044 p->transfer_syntax = *transfer_syntax;
2046 init_ncacn_hdr(p->conn, &pkt);
2048 pkt.ptype = DCERPC_PKT_ALTER;
2049 pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
2050 pkt.call_id = p->conn->call_id;
2051 pkt.auth_length = 0;
2053 if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {
2054 pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
2057 if (p->binding->flags & DCERPC_HEADER_SIGNING) {
2058 pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
2061 pkt.u.alter.max_xmit_frag = 5840;
2062 pkt.u.alter.max_recv_frag = 5840;
2063 pkt.u.alter.assoc_group_id = p->binding->assoc_group_id;
2064 pkt.u.alter.num_contexts = 1;
2065 pkt.u.alter.ctx_list = talloc_array(c, struct dcerpc_ctx_list, 1);
2066 if (composite_nomem(pkt.u.alter.ctx_list, c)) return c;
2067 pkt.u.alter.ctx_list[0].context_id = p->context_id;
2068 pkt.u.alter.ctx_list[0].num_transfer_syntaxes = 1;
2069 pkt.u.alter.ctx_list[0].abstract_syntax = p->syntax;
2070 pkt.u.alter.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
2071 pkt.u.alter.auth_info = data_blob(NULL, 0);
2073 /* construct the NDR form of the packet */
2074 c->status = ncacn_push_auth(&blob, mem_ctx, &pkt,
2075 p->conn->security_state.auth_info);
2076 if (!composite_is_ok(c)) return c;
2078 p->conn->transport.recv_data = dcerpc_recv_data;
2081 * we allocate a dcerpc_request so we can be in the same
2082 * request queue as normal requests
2084 req = talloc_zero(c, struct rpc_request);
2085 if (composite_nomem(req, c)) return c;
2087 req->state = RPC_REQUEST_PENDING;
2088 req->call_id = pkt.call_id;
2089 req->async.private_data = c;
2090 req->async.callback = dcerpc_composite_fail;
2092 req->recv_handler = dcerpc_alter_recv_handler;
2093 DLIST_ADD_END(p->conn->pending, req, struct rpc_request *);
2094 talloc_set_destructor(req, dcerpc_req_dequeue);
2096 c->status = p->conn->transport.send_request(p->conn, &blob, true);
2097 if (!composite_is_ok(c)) return c;
2099 event_add_timed(c->event_ctx, req,
2100 timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
2101 dcerpc_timeout_handler, req);
2106 NTSTATUS dcerpc_alter_context_recv(struct composite_context *ctx)
2108 NTSTATUS result = composite_wait(ctx);
2114 send a dcerpc alter_context request
2116 _PUBLIC_ NTSTATUS dcerpc_alter_context(struct dcerpc_pipe *p,
2117 TALLOC_CTX *mem_ctx,
2118 const struct ndr_syntax_id *syntax,
2119 const struct ndr_syntax_id *transfer_syntax)
2121 struct composite_context *creq;
2122 creq = dcerpc_alter_context_send(p, mem_ctx, syntax, transfer_syntax);
2123 return dcerpc_alter_context_recv(creq);