2 * Unix SMB/CIFS implementation.
3 * DCERPC client routines
5 * Copyright (C) Stefan Metzmacher 2011
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "system/network.h"
24 #include "lib/util/tevent_ntstatus.h"
25 #include "lib/tsocket/tsocket.h"
26 #include "librpc/gen_ndr/ndr_dcerpc.h"
27 #include "source3/librpc/rpc/dcerpc.h"
28 #include "source4/librpc/rpc/dcerpc.h"
29 #include "auth/gensec/gensec.h"
30 #include "librpc/rpc/dcerpc_connection.h"
31 #include "../lib/util/dlinklist.h"
33 struct dcerpc_association;
34 struct dcerpc_connection;
35 struct dcerpc_security;
36 struct dcerpc_presentation;
39 struct dcerpc_association {
40 uint32_t assoc_group_id;
41 uint16_t client_features;
44 uint32_t next_call_id;
47 struct dcerpc_connection {
48 struct dcerpc_association *assoc;
51 struct tstream_context *stream;
52 dcerpc_connection_use_trans_fn use_trans_fn;
53 struct tevent_queue *write_queue;
57 uint16_t max_xmit_frag;
58 uint16_t max_recv_frag;
59 bool concurrent_multiplex;
63 uint32_t next_sec_context_id;
64 uint16_t next_pres_context_id;
67 struct tevent_queue *out_queue;
68 struct dcerpc_call *list;
69 struct dcerpc_call *active;
70 struct dcerpc_call *new_call;
74 struct tevent_context *ev;
75 struct tevent_req *subreq;
79 struct dcerpc_security {
81 enum dcerpc_AuthType auth_type;
82 enum dcerpc_AuthLevel auth_level;
83 struct gensec_security *gensec;
84 bool client_hdr_signing;
86 bool verified_bitmask1;
89 struct dcerpc_presentation {
91 const struct ndr_interface_table *table;
92 struct ndr_syntax_id transfer;
94 struct dcerpc_ctx_list req;
95 struct dcerpc_ack_ctx ack;
97 bool verified_pcontext;
101 struct dcerpc_call *prev, *next;
104 struct dcerpc_security *sec;
105 struct dcerpc_presentation *pres;
108 struct tevent_req *req;
109 NTSTATUS (*handler)(struct tevent_req *req,
110 struct ncacn_packet *pkt,
115 struct dcerpc_association *dcerpc_association_create(TALLOC_CTX *mem_ctx,
116 uint16_t client_features)
118 struct dcerpc_association *assoc;
120 assoc = talloc_zero(mem_ctx, struct dcerpc_association);
125 assoc->next_call_id = 1;
127 assoc->client_features = client_features;
132 struct dcerpc_connection *dcerpc_connection_create(TALLOC_CTX *mem_ctx,
133 struct dcerpc_association *assoc,
134 struct tstream_context **stream)
136 struct dcerpc_connection *conn;
138 conn = talloc_zero(mem_ctx, struct dcerpc_connection);
144 conn->transport.stream = talloc_move(conn, stream);
145 conn->transport.write_queue = tevent_queue_create(conn, "write_queue");
146 if (conn->transport.write_queue == NULL) {
151 conn->features.max_xmit_frag = 4280;
152 conn->features.max_recv_frag = 4280;
154 conn->calls.out_queue = tevent_queue_create(conn, "out_queue");
155 if (conn->calls.out_queue == NULL) {
163 void dcerpc_connection_set_use_trans_fn(struct dcerpc_connection *conn,
164 dcerpc_connection_use_trans_fn fn)
166 conn->transport.use_trans_fn = fn;
169 struct dcerpc_security *dcerpc_security_allocate(
171 struct dcerpc_connection *conn,
172 enum dcerpc_AuthType auth_type,
173 enum dcerpc_AuthLevel auth_level,
174 struct gensec_security **gensec)
176 struct dcerpc_security *sec;
178 sec = talloc_zero(mem_ctx, struct dcerpc_security);
183 sec->context_id = conn->next_sec_context_id++;
184 sec->auth_type = auth_type;
185 sec->auth_level = auth_level;
187 if (gensec != NULL) {
188 sec->gensec = talloc_move(sec, gensec);
194 struct dcerpc_presentation *dcerpc_presentation_allocate(
196 struct dcerpc_connection *conn,
197 const struct ndr_interface_table *table,
198 const struct ndr_syntax_id *transfer)
200 struct dcerpc_presentation *pres;
202 pres = talloc_zero(mem_ctx, struct dcerpc_presentation);
207 pres->context_id = conn->next_pres_context_id++;
209 pres->transfer = *transfer;
211 pres->negotiate.req.abstract_syntax = table->syntax_id;
212 pres->negotiate.req.context_id = pres->context_id;
213 pres->negotiate.req.num_transfer_syntaxes = 1;
214 pres->negotiate.req.transfer_syntaxes = &pres->transfer;
216 pres->negotiate.ack.result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
217 pres->negotiate.ack.reason.value =
218 DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
223 struct dcerpc_presentation *dcerpc_presentation_test_copy(
225 const struct dcerpc_presentation *pres1,
226 const uint32_t *context_id,
227 const struct ndr_interface_table *table,
228 const struct ndr_syntax_id *transfer)
230 struct dcerpc_presentation *pres2;
232 pres2 = talloc_zero(mem_ctx, struct dcerpc_presentation);
238 if (context_id != NULL) {
239 pres2->context_id = *context_id;
242 pres2->table = table;
244 if (transfer != NULL) {
245 pres2->transfer = *transfer;
248 pres2->negotiate.req.abstract_syntax = pres2->table->syntax_id;
249 pres2->negotiate.req.context_id = pres2->context_id;
250 pres2->negotiate.req.num_transfer_syntaxes = 1;
251 pres2->negotiate.req.transfer_syntaxes = &pres2->transfer;
253 pres2->negotiate.ack.result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
254 pres2->negotiate.ack.reason.value =
255 DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
260 NTSTATUS dcerpc_presentation_status(const struct dcerpc_presentation *pres)
262 const struct dcerpc_ack_ctx *ack = &pres->negotiate.ack;
264 switch (ack->result) {
265 case DCERPC_BIND_ACK_RESULT_ACCEPTANCE:
268 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
270 * We have not asked for this...
272 return NT_STATUS_RPC_PROTOCOL_ERROR;
277 switch (ack->reason.value) {
278 case DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED:
279 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
281 case DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED:
282 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
288 return NT_STATUS_UNSUCCESSFUL;
291 struct dcerpc_call *dcerpc_call_allocate(TALLOC_CTX *mem_ctx,
292 struct dcerpc_association *assoc,
293 struct dcerpc_security *sec,
294 struct dcerpc_presentation *pres)
296 struct dcerpc_call *call;
298 call = talloc_zero(mem_ctx, struct dcerpc_call);
303 call->call_id = assoc->next_call_id++;
311 static NTSTATUS dcerpc_guess_pdu_sizes(struct dcerpc_security *sec,
314 size_t max_xmit_frag,
315 size_t pad_alignment,
316 size_t *data_to_send,
324 /* no auth token cases first */
325 switch (sec->auth_level) {
326 case DCERPC_AUTH_LEVEL_NONE:
327 case DCERPC_AUTH_LEVEL_CONNECT:
328 case DCERPC_AUTH_LEVEL_PACKET:
329 max_len = max_xmit_frag - header_len;
330 *data_to_send = MIN(max_len, data_left);
333 *frag_len = header_len + *data_to_send;
336 case DCERPC_AUTH_LEVEL_PRIVACY:
337 case DCERPC_AUTH_LEVEL_INTEGRITY:
338 if (sec->auth_type == DCERPC_AUTH_TYPE_NONE) {
339 return NT_STATUS_INVALID_PARAMETER_MIX;
341 if (sec->gensec == NULL) {
342 return NT_STATUS_INVALID_PARAMETER_MIX;
347 return NT_STATUS_INVALID_PARAMETER;
351 /* Sign/seal case, calculate auth and pad lengths */
353 max_len = max_xmit_frag - header_len - DCERPC_AUTH_TRAILER_LENGTH;
355 *auth_len = gensec_sig_size(sec->gensec, max_len);
357 max_len -= *auth_len;
359 *data_to_send = MIN(max_len, data_left);
361 mod_len = (header_len + *data_to_send) % pad_alignment;
363 *pad_len = pad_alignment - mod_len;
368 if (*data_to_send + *pad_len > max_len) {
369 *data_to_send -= pad_alignment;
372 *frag_len = header_len + *data_to_send + *pad_len
373 + DCERPC_AUTH_TRAILER_LENGTH + *auth_len;
378 static NTSTATUS dcerpc_ncacn_push_auth(DATA_BLOB *blob,
380 struct ncacn_packet *pkt,
381 struct dcerpc_auth *auth_info)
383 struct ndr_push *ndr;
384 enum ndr_err_code ndr_err;
386 ndr = ndr_push_init_ctx(mem_ctx);
388 return NT_STATUS_NO_MEMORY;
391 if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
392 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
395 if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
396 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
400 pkt->auth_length = auth_info->credentials.length;
402 // pkt->auth_length = 0;
405 ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
406 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
407 return ndr_map_error2ntstatus(ndr_err);
412 /* the s3 rpc server doesn't handle auth padding in
413 bind requests. Use zero auth padding to keep us
414 working with old servers */
415 uint32_t offset = ndr->offset;
416 ndr_err = ndr_push_align(ndr, 16);
417 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
418 return ndr_map_error2ntstatus(ndr_err);
420 auth_info->auth_pad_length = ndr->offset - offset;
422 auth_info->auth_pad_length = 0;
424 ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, auth_info);
425 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
426 return ndr_map_error2ntstatus(ndr_err);
430 *blob = ndr_push_blob(ndr);
432 /* fill in the frag length */
433 dcerpc_set_frag_length(blob, blob->length);
438 static NTSTATUS dcerpc_ncacn_packet_blob(TALLOC_CTX *mem_ctx,
439 enum dcerpc_pkt_type ptype,
441 uint16_t auth_length,
443 union dcerpc_payload *u,
446 struct ncacn_packet r;
450 r.rpc_vers_minor = 0;
452 r.pfc_flags = pfc_flags;
453 r.drep[0] = DCERPC_DREP_LE;
457 r.auth_length = auth_length;
461 status = dcerpc_ncacn_push_auth(blob, mem_ctx, &r, NULL);
462 if (!NT_STATUS_IS_OK(status)) {
466 if (DEBUGLEVEL >= 10) {
467 /* set frag len for print function */
468 r.frag_length = blob->length;
469 NDR_PRINT_DEBUG(ncacn_packet, &r);
475 #define DCERPC_PAYLOAD_PADDING_SIZE 16 //TODO???
477 static NTSTATUS dcerpc_auth_blob(TALLOC_CTX *mem_ctx,
478 enum dcerpc_AuthType auth_type,
479 enum dcerpc_AuthLevel auth_level,
480 uint8_t auth_pad_length,
481 uint32_t auth_context_id,
482 const DATA_BLOB *credentials,
485 struct dcerpc_auth r;
486 enum ndr_err_code ndr_err;
488 r.auth_type = auth_type;
489 r.auth_level = auth_level;
490 r.auth_pad_length = auth_pad_length;
492 r.auth_context_id = auth_context_id;
493 r.credentials = *credentials;
495 ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r,
496 (ndr_push_flags_fn_t)ndr_push_dcerpc_auth);
497 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
498 return ndr_map_error2ntstatus(ndr_err);
501 if (DEBUGLEVEL >= 10) {
502 NDR_PRINT_DEBUG(dcerpc_auth, &r);
508 static NTSTATUS dcerpc_response_auth_blob(struct dcerpc_security *sec,
512 char pad[DCERPC_PAYLOAD_PADDING_SIZE] = { 0, };
515 uint16_t data_and_pad_len = 0;
518 if (rpc_out->length < DCERPC_RESPONSE_LENGTH) {
519 return NT_STATUS_INVALID_PARAMETER_MIX;
522 if (sec->auth_type == DCERPC_AUTH_TYPE_NONE ||
523 sec->auth_type == DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM) {
527 if (sec->gensec == NULL) {
528 return NT_STATUS_INVALID_PARAMETER_MIX;
532 /* Copy the sign/seal padding data. */
533 if (!data_blob_append(NULL, rpc_out, pad, pad_len)) {
534 return NT_STATUS_NO_MEMORY;
538 data_and_pad_len = rpc_out->length - DCERPC_RESPONSE_LENGTH;
540 /* marshall the dcerpc_auth with an actually empty auth_blob.
541 * This is needed because the ntmlssp signature includes the
542 * auth header. We will append the actual blob later. */
543 auth_blob = data_blob_null;
544 status = dcerpc_auth_blob(rpc_out->data,
551 if (!NT_STATUS_IS_OK(status)) {
555 /* append the header */
556 if (!data_blob_append(NULL, rpc_out,
557 auth_info.data, auth_info.length)) {
558 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
559 (unsigned int)auth_info.length));
560 return NT_STATUS_NO_MEMORY;
562 data_blob_free(&auth_info);
564 switch (sec->auth_level) {
565 case DCERPC_AUTH_LEVEL_PRIVACY:
566 /* Data portion is encrypted. */
567 status = gensec_seal_packet(sec->gensec,
570 + DCERPC_RESPONSE_LENGTH,
575 if (!NT_STATUS_IS_OK(status)) {
580 case DCERPC_AUTH_LEVEL_INTEGRITY:
581 /* Data is signed. */
582 status = gensec_sign_packet(sec->gensec,
585 + DCERPC_RESPONSE_LENGTH,
590 if (!NT_STATUS_IS_OK(status)) {
597 smb_panic("bad auth level");
599 return NT_STATUS_INVALID_PARAMETER;
602 /* Finally attach the blob. */
603 if (!data_blob_append(NULL, rpc_out,
604 auth_blob.data, auth_blob.length)) {
605 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
606 (unsigned int)auth_blob.length));
607 return NT_STATUS_NO_MEMORY;
609 data_blob_free(&auth_blob);
614 static NTSTATUS dcerpc_check_pdu_auth(struct dcerpc_security *sec,
615 struct ncacn_packet *pkt,
616 DATA_BLOB *pkt_trailer,
622 struct dcerpc_auth auth_info;
623 uint32_t auth_length;
627 switch (sec->auth_level) {
628 case DCERPC_AUTH_LEVEL_PRIVACY:
629 DEBUG(10, ("Requested Privacy.\n"));
632 case DCERPC_AUTH_LEVEL_INTEGRITY:
633 DEBUG(10, ("Requested Integrity.\n"));
636 case DCERPC_AUTH_LEVEL_CONNECT:
637 if (pkt->auth_length != 0) {
643 case DCERPC_AUTH_LEVEL_NONE:
644 if (pkt->auth_length != 0) {
645 DEBUG(3, ("Got non-zero auth len on non "
646 "authenticated connection!\n"));
647 return NT_STATUS_INVALID_PARAMETER;
653 DEBUG(3, ("Unimplemented Auth Level %d",
655 return NT_STATUS_INVALID_PARAMETER;
658 /* Paranioa checks for auth_length. */
659 if (pkt->auth_length > pkt->frag_length) {
660 return NT_STATUS_INFO_LENGTH_MISMATCH;
662 if (((unsigned int)pkt->auth_length
663 + DCERPC_AUTH_TRAILER_LENGTH < (unsigned int)pkt->auth_length) ||
664 ((unsigned int)pkt->auth_length
665 + DCERPC_AUTH_TRAILER_LENGTH < DCERPC_AUTH_TRAILER_LENGTH)) {
666 /* Integer wrap attempt. */
667 return NT_STATUS_INFO_LENGTH_MISMATCH;
670 status = dcerpc_pull_auth_trailer(pkt, pkt, pkt_trailer,
671 &auth_info, &auth_length, false);
672 if (!NT_STATUS_IS_OK(status)) {
676 if (auth_info.auth_type != sec->auth_type) {
677 return NT_STATUS_RPC_PROTOCOL_ERROR;
680 if (auth_info.auth_level != sec->auth_level) {
681 return NT_STATUS_RPC_PROTOCOL_ERROR;
684 if (auth_info.auth_context_id != sec->context_id) {
685 return NT_STATUS_RPC_PROTOCOL_ERROR;
688 data = data_blob_const(raw_pkt->data + header_size,
689 pkt_trailer->length - auth_length);
690 full_pkt = data_blob_const(raw_pkt->data,
691 raw_pkt->length - auth_info.credentials.length);
693 switch (sec->auth_type) {
694 case DCERPC_AUTH_TYPE_NONE:
695 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
701 switch (sec->auth_level) {
702 case DCERPC_AUTH_LEVEL_PRIVACY:
703 /* Data portion is encrypted. */
704 status = gensec_unseal_packet(sec->gensec,
709 &auth_info.credentials);
710 if (!NT_STATUS_IS_OK(status)) {
715 case DCERPC_AUTH_LEVEL_INTEGRITY:
716 /* Data is signed. */
717 status = gensec_check_packet(sec->gensec,
722 &auth_info.credentials);
723 if (!NT_STATUS_IS_OK(status)) {
728 return NT_STATUS_INVALID_PARAMETER;
730 /* TODO: remove later
731 * this is still needed because in the server code the
732 * pkt_trailer actually has a copy of the raw data, and they
733 * are still both used in later calls */
734 if (sec->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
735 memcpy(pkt_trailer->data, data.data, data.length);
738 *pad_len = auth_info.auth_pad_length;
739 data_blob_free(&auth_info.credentials);
743 static void dcerpc_connection_loop(struct tevent_req *subreq);
745 static NTSTATUS dcerpc_connection_loop_restart(struct dcerpc_connection *conn,
746 struct tevent_context *ev)
749 return NT_STATUS_INVALID_PARAMETER; // TODO...
752 if (conn->loop.subreq) {
753 if (conn->loop.ev != ev) {
754 return NT_STATUS_INVALID_PARAMETER; // TODO...
759 if (conn->calls.list == NULL) {
760 conn->loop.ev = NULL;
764 conn->loop.subreq = dcerpc_read_ncacn_packet_send(conn,
766 conn->transport.stream);
767 if (conn->loop.subreq == NULL) {
768 return NT_STATUS_NO_MEMORY;
770 tevent_req_set_callback(conn->loop.subreq, dcerpc_connection_loop, conn);
775 static void dcerpc_connection_loop(struct tevent_req *subreq)
777 struct dcerpc_connection *conn =
778 tevent_req_callback_data(subreq,
779 struct dcerpc_connection);
781 struct ncacn_packet *pkt;
783 struct dcerpc_call *call;
784 bool valid_type = false;
785 bool allow_fragments = false;
787 conn->loop.subreq = NULL;
789 error = dcerpc_read_ncacn_packet_recv(subreq, subreq, &pkt, &pdu);
790 if (!NT_STATUS_IS_OK(error)) {
792 // disconnect and notify pending calls
796 if (DEBUGLEVEL >= 10) {
797 NDR_PRINT_DEBUG(ncacn_packet, pkt);
800 switch (pkt->ptype) {
801 case DCERPC_PKT_REQUEST:
802 /* Ordinary request. */
804 allow_fragments = true;
807 case DCERPC_PKT_PING:
808 /* Connectionless is server alive ? */
811 case DCERPC_PKT_RESPONSE:
812 /* Ordinary reply. */
814 allow_fragments = true;
817 case DCERPC_PKT_FAULT:
818 /* Fault in processing of call. */
822 case DCERPC_PKT_WORKING:
823 /* Connectionless reply to a ping when server busy. */
826 case DCERPC_PKT_NOCALL:
827 /* Connectionless reply to a ping when server has lost part of clients call. */
830 case DCERPC_PKT_REJECT:
831 /* Refuse a request with a code. */
837 case DCERPC_PKT_CL_CANCEL:
840 case DCERPC_PKT_FACK:
843 case DCERPC_PKT_CANCEL_ACK:
844 /* Server ACK to client cancel request. */
847 case DCERPC_PKT_BIND:
848 /* Bind to interface. */
852 case DCERPC_PKT_BIND_ACK:
853 /* Server ack of bind. */
857 case DCERPC_PKT_BIND_NAK:
858 /* Server nack of bind. */
862 case DCERPC_PKT_ALTER:
867 case DCERPC_PKT_ALTER_RESP:
868 /* Reply to alter auth. */
872 case DCERPC_PKT_AUTH3:
873 /* not the real name! this is undocumented! */
877 case DCERPC_PKT_SHUTDOWN:
878 /* Server to client request to shutdown. */
882 case DCERPC_PKT_CO_CANCEL:
883 /* Connection-oriented cancel request. */
887 case DCERPC_PKT_ORPHANED:
888 /* Client telling server it's aborting a partially sent request or telling server to stop sending replies. */
893 /* RTS packets used in ncacn_http */
899 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
903 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
904 if (!allow_fragments) {
906 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
911 if (conn->calls.active != NULL) {
913 if (pkt->call_id != conn->calls.active->call_id) {
915 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
919 if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) {
921 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
925 call = conn->calls.active;
927 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
928 conn->calls.active = NULL;
931 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
933 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
937 call = conn->calls.list;
940 for (call = conn->calls.list; call; call = call->next) {
941 if (call->call_id == pkt->call_id) {
947 call = conn->calls.new_call;
952 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
956 if (call->incoming.handler == NULL) {
958 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
962 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
963 conn->calls.active = call;
967 // reassemble and return
970 error = call->incoming.handler(call->incoming.req, pkt, pdu);
972 if (!NT_STATUS_IS_OK(error)) {
973 // disconnect and notify pending calls
977 if (conn->calls.new_call == NULL) {
978 conn->loop.ev = NULL;
982 error = dcerpc_connection_loop_restart(conn, conn->loop.ev);
983 if (!NT_STATUS_IS_OK(error)) {
984 // disconnect and notify pending calls
989 struct dcerpc_do_bind_out_frag;
991 struct dcerpc_do_bind_state {
992 struct tevent_context *ev;
993 struct dcerpc_connection *conn;
994 struct dcerpc_call *call;
995 struct dcerpc_security *sec;
996 bool proposed_hdr_signing;
1000 struct dcerpc_do_bind_out_frag *out_frag;
1002 struct dcerpc_presentation **pres;
1003 uint32_t remaining_pres;
1006 struct dcerpc_ctx_list *ctx_list;
1007 struct ndr_syntax_id features;
1010 struct dcerpc_do_bind_out_frag {
1011 struct tevent_context *ev;
1012 struct dcerpc_connection *conn;
1013 struct tevent_req *req;
1014 enum dcerpc_pkt_type ptype;
1016 struct iovec vector;
1017 struct tevent_req *subreq_wait1;
1018 struct tevent_req *subreq_wait2;
1021 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
1022 enum tevent_req_state req_state);
1024 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq);
1025 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq);
1027 static NTSTATUS dcerpc_do_bind_handle_in_frag(struct tevent_req *req,
1028 struct ncacn_packet *pkt,
1031 struct tevent_req *dcerpc_do_bind_send(TALLOC_CTX *mem_ctx,
1032 struct tevent_context *ev,
1033 struct dcerpc_connection *conn,
1034 struct dcerpc_call *call,
1035 struct dcerpc_security *sec,
1037 struct dcerpc_presentation **pres)
1039 struct tevent_req *req;
1040 struct dcerpc_do_bind_state *state;
1041 struct tevent_req *subreq;
1043 req = tevent_req_create(mem_ctx, &state,
1044 struct dcerpc_do_bind_state);
1052 state->remaining_pres = num_pres;
1053 state->num_pres = num_pres;
1056 state->call->incoming.req = req;
1057 state->call->incoming.handler = dcerpc_do_bind_handle_in_frag;
1058 DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
1059 tevent_req_defer_callback(req, ev);
1060 tevent_req_set_cleanup_fn(req, dcerpc_do_bind_cleanup);
1062 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1063 subreq = gensec_update_send(state, ev,
1066 if (tevent_req_nomem(subreq, req)) {
1067 return tevent_req_post(req, ev);
1069 tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
1074 state->sec_status = NT_STATUS_OK;
1076 subreq = tevent_queue_wait_send(state, state->ev,
1077 state->conn->calls.out_queue);
1078 if (tevent_req_nomem(subreq, req)) {
1079 return tevent_req_post(req, ev);
1081 tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
1086 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
1087 enum tevent_req_state req_state)
1089 struct dcerpc_do_bind_state *state =
1090 tevent_req_data(req,
1091 struct dcerpc_do_bind_state);
1093 if (state->out_frag != NULL) {
1094 state->out_frag->req = NULL;
1095 state->out_frag = NULL;
1098 if (state->call != NULL) {
1099 ZERO_STRUCT(state->call->incoming);
1100 DLIST_REMOVE(state->conn->calls.list, state->call);
1105 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq)
1107 struct tevent_req *req =
1108 tevent_req_callback_data(subreq,
1110 struct dcerpc_do_bind_state *state =
1111 tevent_req_data(req,
1112 struct dcerpc_do_bind_state);
1115 data_blob_free(&state->sec_out);
1116 status = gensec_update_recv(subreq, state, &state->sec_out);
1117 TALLOC_FREE(subreq);
1118 data_blob_free(&state->sec_in);
1119 state->sec_status = status;
1120 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1121 status = NT_STATUS_OK;
1123 if (!NT_STATUS_IS_OK(status)) {
1124 tevent_req_nterror(req, status);
1128 if (NT_STATUS_IS_OK(state->sec_status) &&
1129 state->sec_out.length == 0)
1131 tevent_req_done(req);
1135 if (state->sec->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1136 state->sec->client_hdr_signing =
1137 gensec_have_feature(state->sec->gensec,
1138 GENSEC_FEATURE_SIGN_PKT_HEADER);
1141 subreq = tevent_queue_wait_send(state, state->ev,
1142 state->conn->calls.out_queue);
1143 if (tevent_req_nomem(subreq, req)) {
1146 tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
1149 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq);
1150 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq);
1151 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq);
1153 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq)
1155 struct tevent_req *req =
1156 tevent_req_callback_data(subreq,
1158 struct dcerpc_do_bind_state *state =
1159 tevent_req_data(req,
1160 struct dcerpc_do_bind_state);
1161 struct dcerpc_do_bind_out_frag *frag;
1162 size_t auth_len = 0;
1164 DATA_BLOB auth_info = data_blob_null;
1165 uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1166 union dcerpc_payload u;
1168 bool require_ack = false;
1169 bool use_trans = true;
1172 ok = tevent_queue_wait_recv(subreq);
1174 //status = NT_STATUS_INTERNAL_ERROR;
1175 tevent_req_oom(req);
1178 TALLOC_FREE(subreq);
1181 * the fragment belongs to the connection instead of the request
1182 * because it has to remain in case the request is canceled
1184 frag = talloc_zero(state->conn, struct dcerpc_do_bind_out_frag);
1185 if (tevent_req_nomem(frag, req)) {
1188 frag->ev = state->ev;
1189 frag->conn = state->conn;
1191 state->out_frag = frag;
1193 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1194 if (state->sec->client_hdr_signing &&
1195 !state->proposed_hdr_signing)
1197 state->proposed_hdr_signing = true;
1198 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1203 //TODO : DCERPC_PFC_FLAG_CONC_MPX
1205 //TODO: remaining_pres
1207 if (!state->conn->features.bind_done) {
1208 frag->ptype = DCERPC_PKT_BIND;
1209 } else if (require_ack) {
1210 frag->ptype = DCERPC_PKT_ALTER;
1211 } else if (state->remaining_pres > 0) {
1212 frag->ptype = DCERPC_PKT_ALTER;
1213 } else if (!NT_STATUS_IS_OK(state->sec_status)) {
1214 frag->ptype = DCERPC_PKT_ALTER;
1216 frag->ptype = DCERPC_PKT_AUTH3;
1219 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1220 status = dcerpc_auth_blob(frag,
1221 state->sec->auth_type,
1222 state->sec->auth_level,
1223 0, /* auth_pad_length */
1224 state->sec->context_id, /* auth_context_id */
1227 if (!NT_STATUS_IS_OK(status)) {
1228 tevent_req_nterror(req, status);
1232 auth_len = auth_info.length;
1235 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1239 state->num_ctx = state->num_pres;
1240 if (!state->conn->assoc->negotiate_done) {
1241 state->num_ctx += 1;
1244 state->ctx_list = talloc_zero_array(frag,
1245 struct dcerpc_ctx_list,
1247 if (tevent_req_nomem(state->ctx_list, req)) {
1251 for (i=0; i < state->num_pres; i++) {
1252 state->ctx_list[i] = state->pres[i]->negotiate.req;
1255 if (!state->conn->assoc->negotiate_done) {
1256 state->features = dcerpc_construct_bind_time_features(
1257 state->conn->assoc->client_features);
1259 state->ctx_list[i].context_id = state->conn->next_pres_context_id;
1261 state->ctx_list[i].abstract_syntax =
1262 state->ctx_list[i-1].abstract_syntax;
1264 state->ctx_list[i].num_transfer_syntaxes = 1;
1265 state->ctx_list[i].transfer_syntaxes = &state->features;
1268 switch (frag->ptype) {
1269 case DCERPC_PKT_BIND:
1270 case DCERPC_PKT_ALTER:
1271 u.bind.max_xmit_frag = state->conn->features.max_xmit_frag;
1272 u.bind.max_recv_frag = state->conn->features.max_recv_frag;
1273 u.bind.assoc_group_id = state->conn->assoc->assoc_group_id;
1274 u.bind.num_contexts = state->num_ctx;
1275 u.bind.ctx_list = state->ctx_list;
1276 u.bind.auth_info = auth_info;
1279 case DCERPC_PKT_AUTH3:
1281 u.auth3.auth_info = auth_info;
1284 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1288 status = dcerpc_ncacn_packet_blob(frag,
1292 state->call->call_id,
1295 if (!NT_STATUS_IS_OK(status)) {
1296 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1297 tevent_req_nterror(req, status);
1301 if (frag->ptype == DCERPC_PKT_AUTH3) {
1305 if (frag->conn->transport.use_trans_fn == NULL) {
1309 if (frag->conn->loop.subreq != NULL) {
1313 if (frag->conn->features.concurrent_multiplex) {
1317 if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
1322 frag->subreq_wait1 = tevent_queue_wait_send(frag,
1324 frag->conn->transport.write_queue);
1325 if (tevent_req_nomem(req, frag->subreq_wait1)) {
1328 tevent_req_set_callback(frag->subreq_wait1,
1329 dcerpc_do_bind_out_frag_trans_wait1,
1332 * we need to block reads until our write is
1333 * the next in the write queue.
1335 frag->conn->loop.subreq = frag->subreq_wait1;
1336 frag->conn->loop.ev = frag->ev;
1340 * We need to add a dcerpc_write_fragment_queue_send/recv()
1343 frag->vector.iov_base = frag->blob.data;
1344 frag->vector.iov_len = frag->blob.length;
1345 subreq = tstream_writev_queue_send(frag, frag->ev,
1346 frag->conn->transport.stream,
1347 frag->conn->transport.write_queue,
1349 if (tevent_req_nomem(subreq, req)) {
1352 tevent_req_set_callback(subreq,
1353 dcerpc_do_bind_out_frag_done,
1357 frag->subreq_wait2 = tevent_queue_wait_send(frag,
1359 frag->conn->transport.write_queue);
1360 if (tevent_req_nomem(req, frag->subreq_wait2)) {
1363 tevent_req_set_callback(frag->subreq_wait2,
1364 dcerpc_do_bind_out_frag_trans_wait2,
1368 if (frag->ptype == DCERPC_PKT_AUTH3) {
1372 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1373 if (tevent_req_nterror(req, status)) {
1378 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq)
1380 struct dcerpc_do_bind_out_frag *frag =
1381 tevent_req_callback_data(subreq,
1382 struct dcerpc_do_bind_out_frag);
1383 struct tevent_req *req = frag->req;
1388 * TODO; what if the caller has been free'ed?
1391 frag->subreq_wait1 = NULL;
1392 frag->conn->loop.subreq = NULL;
1394 ok = tevent_queue_wait_recv(subreq);
1396 status = NT_STATUS_INTERNAL_ERROR;
1399 tevent_req_nterror(req, status);
1401 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1405 if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
1407 * We added 3 entries into the queue,
1408 * wait1, writev and wait2.
1410 * There's more to write, we should not block
1411 * further writev calls for a trans call.
1413 * The wait2 stage will trigger the read.
1415 TALLOC_FREE(subreq);
1420 * we don't need wait2 anymore, we're sure that
1421 * we'll do a trans call.
1423 TALLOC_FREE(frag->subreq_wait2);
1425 status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
1426 if (!NT_STATUS_IS_OK(status)) {
1429 tevent_req_nterror(req, status);
1431 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1435 /* we free subreq after tstream_cli_np_use_trans */
1436 TALLOC_FREE(subreq);
1438 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1439 if (!NT_STATUS_IS_OK(status)) {
1442 tevent_req_nterror(req, status);
1444 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1449 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq)
1451 struct dcerpc_do_bind_out_frag *frag =
1452 tevent_req_callback_data(subreq,
1453 struct dcerpc_do_bind_out_frag);
1454 struct tevent_req *req = frag->req;
1460 * If the caller has been free'ed, we have should
1461 * ignore any errors and just free 'frag'
1464 struct dcerpc_do_bind_state *state =
1465 tevent_req_data(req,
1466 struct dcerpc_do_bind_state);
1468 state->out_frag = NULL;
1471 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1472 TALLOC_FREE(subreq);
1475 status = map_nt_error_from_unix_common(sys_errno);
1477 tevent_req_nterror(req, status);
1482 if (frag->ptype == DCERPC_PKT_AUTH3) {
1487 tevent_req_done(req);
1491 if (frag->subreq_wait2 != NULL) {
1497 /* we need to wait for incoming pdus */
1500 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq)
1502 struct dcerpc_do_bind_out_frag *frag =
1503 tevent_req_callback_data(subreq,
1504 struct dcerpc_do_bind_out_frag);
1505 struct tevent_req *req = frag->req;
1509 frag->subreq_wait2 = NULL;
1511 ok = tevent_queue_wait_recv(subreq);
1513 status = NT_STATUS_INTERNAL_ERROR;
1516 tevent_req_nterror(req, status);
1518 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1522 TALLOC_FREE(subreq);
1524 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1525 if (!NT_STATUS_IS_OK(status)) {
1528 tevent_req_nterror(req, status);
1530 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1536 /* we need to wait for incoming pdus */
1539 static NTSTATUS dcerpc_do_bind_handle_in_frag(struct tevent_req *req,
1540 struct ncacn_packet *pkt,
1543 struct dcerpc_do_bind_state *state =
1544 tevent_req_data(req,
1545 struct dcerpc_do_bind_state);
1547 struct dcerpc_presentation *last_pres = NULL;
1548 size_t num_pres_ok = 0;
1551 /* Ensure we have the correct type. */
1552 switch (pkt->ptype) {
1553 case DCERPC_PKT_BIND_ACK:
1554 case DCERPC_PKT_ALTER_RESP:
1555 if (!state->conn->features.bind_done) {
1556 if (pkt->u.bind_ack.max_recv_frag < 1234) {
1557 return NT_STATUS_RPC_PROTOCOL_ERROR;
1559 if (pkt->u.bind_ack.max_xmit_frag < 1234) {
1560 return NT_STATUS_RPC_PROTOCOL_ERROR;
1562 state->conn->features.max_recv_frag =
1563 pkt->u.bind_ack.max_recv_frag;
1564 state->conn->features.max_xmit_frag =
1565 pkt->u.bind_ack.max_xmit_frag;
1567 if (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) {
1568 state->conn->features.concurrent_multiplex = true;
1571 state->conn->features.bind_done = true;
1574 if (!state->conn->assoc->negotiate_done) {
1575 state->conn->assoc->negotiate_done = true;
1576 state->conn->assoc->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
1579 if (pkt->u.bind_ack.assoc_group_id != state->conn->assoc->assoc_group_id) {
1580 return NT_STATUS_RPC_PROTOCOL_ERROR;
1583 if (pkt->u.bind_ack.num_results > state->num_ctx) {
1584 return NT_STATUS_RPC_PROTOCOL_ERROR;
1587 state->remaining_pres = 0;
1589 if (state->proposed_hdr_signing) {
1590 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1591 state->sec->hdr_signing = true;
1595 for (i = 0; i < pkt->u.bind_ack.num_results; i++) {
1596 struct dcerpc_ack_ctx *ack = &pkt->u.bind_ack.ctx_list[i];
1598 if (i < state->num_pres) {
1599 struct dcerpc_ack_ctx *pack =
1600 &state->pres[i]->negotiate.ack;
1602 if (ack->result == DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1603 return NT_STATUS_RPC_PROTOCOL_ERROR;
1606 if (ack->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1612 if (pack->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1614 * if a presentation context was valid it must
1615 * be valid for the lifetime of the connection
1617 return NT_STATUS_RPC_PROTOCOL_ERROR;
1621 last_pres = state->pres[i];
1625 if (ack->result != DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1629 state->conn->assoc->features = state->conn->assoc->client_features;
1630 state->conn->assoc->features &= ack->reason.negotiate;
1633 for (i = 0; i < state->num_pres; i++) {
1634 struct dcerpc_ack_ctx *ack = &state->pres[i]->negotiate.ack;
1637 if (ack->result != DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1641 ok = ndr_syntax_id_equal(&state->pres[i]->transfer,
1644 return NT_STATUS_RPC_PROTOCOL_ERROR;
1648 if (num_pres_ok == 0 && last_pres != NULL) {
1649 status = dcerpc_presentation_status(last_pres);
1650 tevent_req_nterror(req, status);
1651 return NT_STATUS_OK;
1654 if (pkt->auth_length >= 8) {
1655 struct tevent_req *subreq;
1657 state->sec_in = data_blob_talloc(state,
1658 pkt->u.bind_ack.auth_info.data + 8,
1659 pkt->u.bind_ack.auth_info.length - 8);
1661 subreq = gensec_update_send(state, state->ev,
1664 if (tevent_req_nomem(subreq, req)) {
1665 return NT_STATUS_OK;
1667 tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
1668 return NT_STATUS_OK;
1671 tevent_req_done(req);
1672 return NT_STATUS_OK;
1674 //case DCERPC_PKT_ALTER_RESP:
1675 if (pkt->auth_length != 0) {
1676 return NT_STATUS_NOT_IMPLEMENTED;
1679 return NT_STATUS_NOT_IMPLEMENTED;
1682 /* Point the return values at the NDR data. */
1683 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
1685 if (pkt->auth_length) {
1686 /* We've already done integer wrap tests in
1687 * dcerpc_check_auth(). */
1688 payload.length = frag.length
1689 - DCERPC_RESPONSE_LENGTH
1691 - DCERPC_AUTH_TRAILER_LENGTH
1694 payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
1697 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1698 if (pkt->drep[0] & DCERPC_DREP_LE) {
1699 state->response.bigendian = false;
1701 state->response.bigendian = true;
1705 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
1706 (long unsigned int)frag.length,
1707 (long unsigned int)payload.length,
1708 (unsigned int)pad_len));
1711 * If this is the first reply, and the allocation hint is
1712 * reasonable, try and set up the reply_pdu DATA_BLOB to the
1716 if ((state->response.blob.length == 0) &&
1717 pkt->u.response.alloc_hint &&
1718 (pkt->u.response.alloc_hint < 15*1024*1024)) {
1719 ok = data_blob_realloc(state, &state->response.blob,
1720 pkt->u.response.alloc_hint);
1722 DEBUG(0, ("reply alloc hint %d too "
1723 "large to allocate\n",
1724 (int)pkt->u.response.alloc_hint));
1725 return NT_STATUS_NO_MEMORY;
1729 new_total = state->response.ofs + payload.length;
1731 if (new_total > 15 * 1024 *1024) {
1732 return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
1735 missing = new_total - state->response.blob.length;
1738 ok = data_blob_realloc(state, &state->response.blob,
1741 DEBUG(0, ("reply alloc hint %d too "
1742 "large to allocate\n",
1743 (int)pkt->u.response.alloc_hint));
1744 return NT_STATUS_NO_MEMORY;
1748 memcpy(state->response.blob.data + state->response.ofs,
1749 payload.data, payload.length);
1750 state->response.ofs += payload.length;
1752 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1753 tevent_req_done(req);//TODO
1754 return NT_STATUS_OK;
1756 return NT_STATUS_OK;
1758 return NT_STATUS_NOT_IMPLEMENTED;
1760 case DCERPC_PKT_FAULT:
1762 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1763 "code %s received from %s!\n",
1764 dcerpc_errstr(talloc_tos(),
1765 pkt->u.fault.status),
1768 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
1769 if (NT_STATUS_IS_OK(status)) {
1770 status = NT_STATUS_RPC_PROTOCOL_ERROR;
1773 tevent_req_nterror(req, status);//TODO
1774 return NT_STATUS_OK;
1776 DEBUG(0, ("Unknown packet type %u received from %s!\n",
1777 (unsigned int)pkt->ptype,
1779 return NT_STATUS_RPC_PROTOCOL_ERROR;
1782 return NT_STATUS_RPC_PROTOCOL_ERROR;
1785 NTSTATUS dcerpc_do_bind_recv(struct tevent_req *req)
1787 struct dcerpc_do_bind_state *state =
1788 tevent_req_data(req,
1789 struct dcerpc_do_bind_state);
1792 if (tevent_req_is_nterror(req, &status)) {
1793 tevent_req_received(req);
1797 if (!NT_STATUS_IS_OK(state->sec_status)) {
1798 status = state->sec_status;
1799 tevent_req_received(req);
1803 tevent_req_received(req);
1804 return NT_STATUS_OK;
1807 struct dcerpc_do_request_out_frag;
1809 struct dcerpc_do_request_state {
1810 struct tevent_context *ev;
1811 struct dcerpc_connection *conn;
1812 struct dcerpc_call *call;
1813 const struct GUID *object;
1816 const DATA_BLOB *blob;
1822 bool verify_bitmask1;
1823 bool verify_pcontext;
1825 struct dcerpc_do_request_out_frag *out_frag;
1833 struct dcerpc_do_request_out_frag {
1834 struct tevent_context *ev;
1835 struct dcerpc_connection *conn;
1836 struct tevent_req *req;
1839 struct iovec vector;
1840 struct tevent_req *subreq_wait1;
1841 struct tevent_req *subreq_wait2;
1844 static void dcerpc_do_request_cleanup(struct tevent_req *req,
1845 enum tevent_req_state req_state);
1847 static void dcerpc_do_request_verification_trailer(struct tevent_req *req);
1848 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
1849 void *private_data);
1851 static NTSTATUS dcerpc_do_request_handle_in_frag(struct tevent_req *req,
1852 struct ncacn_packet *pkt,
1855 struct tevent_req *dcerpc_do_request_send(TALLOC_CTX *mem_ctx,
1856 struct tevent_context *ev,
1857 struct dcerpc_connection *conn,
1858 struct dcerpc_call *call,
1859 const struct GUID *object,
1861 const DATA_BLOB *request,
1864 struct tevent_req *req;
1865 struct dcerpc_do_request_state *state;
1868 req = tevent_req_create(mem_ctx, &state,
1869 struct dcerpc_do_request_state);
1876 state->object = object;
1877 state->opnum = opnum;
1878 state->request.blob = request;
1879 state->request.bigendian = bigendian;
1881 dcerpc_do_request_verification_trailer(req);
1882 if (!tevent_req_is_in_progress(req)) {
1883 return tevent_req_post(req, ev);
1886 state->call->incoming.req = req;
1887 state->call->incoming.handler = dcerpc_do_request_handle_in_frag;
1888 DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
1889 tevent_req_defer_callback(req, ev);
1890 tevent_req_set_cleanup_fn(req, dcerpc_do_request_cleanup);
1892 ok = tevent_queue_add(state->conn->calls.out_queue,
1895 dcerpc_do_request_out_frag_next,
1898 tevent_req_nomem(NULL, req);
1899 return tevent_req_post(req, ev);
1905 static void dcerpc_do_request_cleanup(struct tevent_req *req,
1906 enum tevent_req_state req_state)
1908 struct dcerpc_do_request_state *state =
1909 tevent_req_data(req,
1910 struct dcerpc_do_request_state);
1912 if (state->out_frag != NULL) {
1913 state->out_frag->req = NULL;
1914 state->out_frag = NULL;
1917 if (state->call != NULL) {
1918 if (state->call == state->conn->calls.active) {
1919 state->conn->calls.active = NULL;
1921 ZERO_STRUCT(state->call->incoming);
1922 DLIST_REMOVE(state->conn->calls.list, state->call);
1927 static void dcerpc_do_request_verification_trailer(struct tevent_req *req)
1929 struct dcerpc_do_request_state *state =
1930 tevent_req_data(req,
1931 struct dcerpc_do_request_state);
1932 struct dcerpc_sec_verification_trailer *t;
1933 struct dcerpc_sec_vt *c = NULL;
1934 struct ndr_push *ndr = NULL;
1935 enum ndr_err_code ndr_err;
1939 if (state->call->sec->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1943 t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1944 if (tevent_req_nomem(t, req)) {
1948 if (!state->call->sec->verified_bitmask1) {
1949 t->commands = talloc_realloc(t, t->commands,
1950 struct dcerpc_sec_vt,
1951 t->count.count + 1);
1952 if (tevent_req_nomem(t->commands, req)) {
1955 c = &t->commands[t->count.count++];
1958 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1959 if (state->call->sec->client_hdr_signing) {
1960 c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1962 state->verify_bitmask1 = true;
1965 if (!state->call->pres->verified_pcontext) {
1966 t->commands = talloc_realloc(t, t->commands,
1967 struct dcerpc_sec_vt,
1968 t->count.count + 1);
1969 if (tevent_req_nomem(t->commands, req)) {
1972 c = &t->commands[t->count.count++];
1975 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1976 c->u.pcontext.abstract_syntax = state->call->pres->table->syntax_id;
1977 c->u.pcontext.transfer_syntax = state->call->pres->transfer;
1979 state->verify_pcontext = true;
1982 if (!state->call->sec->hdr_signing) {
1983 t->commands = talloc_realloc(t, t->commands,
1984 struct dcerpc_sec_vt,
1985 t->count.count + 1);
1986 if (tevent_req_nomem(t->commands, req)) {
1989 c = &t->commands[t->count.count++];
1992 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1993 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1994 if (state->request.bigendian) {
1995 c->u.header2.drep[0] = 0;
1997 c->u.header2.drep[0] = DCERPC_DREP_LE;
1999 c->u.header2.drep[1] = 0;
2000 c->u.header2.drep[2] = 0;
2001 c->u.header2.drep[3] = 0;
2002 c->u.header2.call_id = state->call->call_id;
2003 c->u.header2.context_id = 0;
2004 c->u.header2.opnum = state->opnum;
2007 if (t->count.count == 0) {
2012 c = &t->commands[t->count.count - 1];
2013 c->command |= DCERPC_SEC_VT_COMMAND_END;
2015 if (DEBUGLEVEL >= 10) {
2016 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
2019 ndr = ndr_push_init_ctx(state);
2020 if (tevent_req_nomem(ndr, req)) {
2024 //TODO if (state->request.bigendian)
2026 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
2027 NDR_SCALARS | NDR_BUFFERS,
2029 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2030 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2031 tevent_req_nterror(req, status);
2034 state->request.trailer = ndr_push_blob(ndr);
2036 align = state->request.blob->length & 0x3;
2043 const uint8_t zeros[4] = { 0, };
2045 ok = data_blob_append(ndr, &state->request.trailer, zeros, pad);
2047 tevent_req_oom(req);
2051 /* move the padding to the start */
2052 p = state->request.trailer.data;
2053 memmove(p + pad, p, state->request.trailer.length - pad);
2060 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq);
2061 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq);
2062 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq);
2064 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
2067 struct dcerpc_do_request_state *state =
2068 tevent_req_data(req,
2069 struct dcerpc_do_request_state);
2070 struct dcerpc_do_request_out_frag *frag;
2071 size_t hdr_len = DCERPC_REQUEST_LENGTH;
2077 size_t data_thistime;
2078 size_t trailer_left;
2079 size_t trailer_thistime = 0;
2081 size_t total_thistime;
2083 union dcerpc_payload u;
2085 struct tevent_req *subreq;
2086 bool use_trans = true;
2088 if (state->object) {
2089 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
2094 * the fragment belongs to the connection instead of the request
2095 * because it has to remain in case the request is canceled
2097 frag = talloc_zero(state->conn, struct dcerpc_do_request_out_frag);
2098 if (tevent_req_nomem(frag, req)) {
2101 frag->ev = state->ev;
2102 frag->conn = state->conn;
2104 state->out_frag = frag;
2106 data_left = state->request.blob->length - state->request.ofs;
2107 trailer_left = state->request.trailer.length - state->request.trailer_ofs;
2108 total_left = data_left + trailer_left;
2109 if (total_left < data_left || total_left < trailer_left) {
2110 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2114 status = dcerpc_guess_pdu_sizes(state->call->sec,
2115 hdr_len, total_left,
2116 state->conn->features.max_xmit_frag,
2119 &frag_len, &auth_len, &pad_len);
2120 if (!NT_STATUS_IS_OK(status)) {
2121 tevent_req_nterror(req, status);
2125 if (state->request.ofs == 0) {
2126 flags |= DCERPC_PFC_FLAG_FIRST;
2129 if (total_thistime == total_left) {
2130 flags |= DCERPC_PFC_FLAG_LAST;
2133 data_thistime = MIN(total_thistime, data_left);
2134 if (data_thistime < total_thistime) {
2135 trailer_thistime = total_thistime - data_thistime;
2138 ZERO_STRUCT(u.request);
2140 u.request.alloc_hint = total_left;
2141 u.request.context_id = state->call->pres->context_id;
2142 u.request.opnum = state->opnum;
2143 if (state->object) {
2144 u.request.object.object = *state->object;
2146 //TODO pass state->request.bigendian
2147 status = dcerpc_ncacn_packet_blob(frag,
2151 state->call->call_id,
2154 if (!NT_STATUS_IS_OK(status)) {
2155 tevent_req_nterror(req, status);
2159 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2160 * compute it right for requests because the auth trailer is missing
2162 dcerpc_set_frag_length(&frag->blob, frag_len);
2164 if (data_thistime > 0) {
2165 const uint8_t *data_ptr;
2167 data_ptr = state->request.blob->data;
2168 data_ptr += state->request.ofs;
2170 /* Copy in the data. */
2171 ok = data_blob_append(frag, &frag->blob,
2172 data_ptr, data_thistime);
2174 tevent_req_oom(req);
2178 state->request.ofs += data_thistime;
2181 if (trailer_thistime > 0) {
2182 const uint8_t *trailer_ptr;
2184 trailer_ptr = state->request.trailer.data;
2185 trailer_ptr += state->request.trailer_ofs;
2187 /* Copy in the data. */
2188 ok = data_blob_append(frag, &frag->blob,
2189 trailer_ptr, trailer_thistime);
2191 tevent_req_oom(req);
2195 state->request.trailer_ofs += trailer_thistime;
2198 switch (state->call->sec->auth_level) {
2199 case DCERPC_AUTH_LEVEL_NONE:
2200 case DCERPC_AUTH_LEVEL_CONNECT:
2201 case DCERPC_AUTH_LEVEL_PACKET:
2203 case DCERPC_AUTH_LEVEL_INTEGRITY:
2204 case DCERPC_AUTH_LEVEL_PRIVACY:
2205 status = dcerpc_response_auth_blob(state->call->sec,
2208 if (!NT_STATUS_IS_OK(status)) {
2209 tevent_req_nterror(req, status);
2214 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2218 frag->is_last = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2220 if (!frag->is_last) {
2224 if (frag->conn->transport.use_trans_fn == NULL) {
2228 if (frag->conn->loop.subreq != NULL) {
2232 if (frag->conn->features.concurrent_multiplex) {
2236 if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
2241 frag->subreq_wait1 = tevent_queue_wait_send(frag,
2243 frag->conn->transport.write_queue);
2244 if (tevent_req_nomem(req, frag->subreq_wait1)) {
2247 tevent_req_set_callback(frag->subreq_wait1,
2248 dcerpc_do_request_out_frag_trans_wait1,
2251 * we need to block reads until our write is
2252 * the next in the write queue.
2254 frag->conn->loop.subreq = frag->subreq_wait1;
2255 frag->conn->loop.ev = frag->ev;
2259 * We need to add a dcerpc_write_fragment_queue_send/recv()
2262 frag->vector.iov_base = frag->blob.data;
2263 frag->vector.iov_len = frag->blob.length;
2264 subreq = tstream_writev_queue_send(frag, frag->ev,
2265 frag->conn->transport.stream,
2266 frag->conn->transport.write_queue,
2268 if (tevent_req_nomem(subreq, req)) {
2271 tevent_req_set_callback(subreq,
2272 dcerpc_do_request_out_frag_done,
2276 frag->subreq_wait2 = tevent_queue_wait_send(frag,
2278 frag->conn->transport.write_queue);
2279 if (tevent_req_nomem(req, frag->subreq_wait2)) {
2282 tevent_req_set_callback(frag->subreq_wait2,
2283 dcerpc_do_request_out_frag_trans_wait2,
2287 if (!frag->is_last) {
2291 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2292 if (tevent_req_nterror(req, status)) {
2297 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq)
2299 struct dcerpc_do_request_out_frag *frag =
2300 tevent_req_callback_data(subreq,
2301 struct dcerpc_do_request_out_frag);
2302 struct tevent_req *req = frag->req;
2307 * TODO; what if the caller has been free'ed?
2310 frag->subreq_wait1 = NULL;
2311 frag->conn->loop.subreq = NULL;
2313 ok = tevent_queue_wait_recv(subreq);
2315 status = NT_STATUS_INTERNAL_ERROR;
2318 tevent_req_nterror(req, status);
2320 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2324 if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
2326 * We added 3 entries into the queue,
2327 * wait1, writev and wait2.
2329 * There's more to write, we should not block
2330 * further writev calls for a trans call.
2332 * The wait2 stage will trigger the read.
2334 TALLOC_FREE(subreq);
2339 * we don't need wait2 anymore, we're sure that
2340 * we'll do a trans call.
2342 TALLOC_FREE(frag->subreq_wait2);
2344 status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
2345 if (!NT_STATUS_IS_OK(status)) {
2348 tevent_req_nterror(req, status);
2350 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2354 /* we free subreq after tstream_cli_np_use_trans */
2355 TALLOC_FREE(subreq);
2357 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2358 if (!NT_STATUS_IS_OK(status)) {
2361 tevent_req_nterror(req, status);
2363 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2368 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq)
2370 struct dcerpc_do_request_out_frag *frag =
2371 tevent_req_callback_data(subreq,
2372 struct dcerpc_do_request_out_frag);
2373 struct tevent_req *req = frag->req;
2379 * If the caller has been free'ed, we have should
2380 * ignore any errors and just free 'frag'
2383 struct dcerpc_do_request_state *state =
2384 tevent_req_data(req,
2385 struct dcerpc_do_request_state);
2387 state->out_frag = NULL;
2390 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2391 TALLOC_FREE(subreq);
2394 status = map_nt_error_from_unix_common(sys_errno);
2396 tevent_req_nterror(req, status);
2401 if (frag->subreq_wait2 != NULL) {
2405 if (frag->is_last) {
2415 dcerpc_do_request_out_frag_next(req, NULL);
2418 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq)
2420 struct dcerpc_do_request_out_frag *frag =
2421 tevent_req_callback_data(subreq,
2422 struct dcerpc_do_request_out_frag);
2423 struct tevent_req *req = frag->req;
2427 frag->subreq_wait2 = NULL;
2429 ok = tevent_queue_wait_recv(subreq);
2431 status = NT_STATUS_INTERNAL_ERROR;
2434 tevent_req_nterror(req, status);
2436 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2440 TALLOC_FREE(subreq);
2442 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2443 if (!NT_STATUS_IS_OK(status)) {
2446 tevent_req_nterror(req, status);
2448 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2454 /* we need to wait for incoming pdus */
2457 static NTSTATUS dcerpc_do_request_handle_in_frag(struct tevent_req *req,
2458 struct ncacn_packet *pkt,
2461 struct dcerpc_do_request_state *state =
2462 tevent_req_data(req,
2463 struct dcerpc_do_request_state);
2472 /* Ensure we have the correct type. */
2473 switch (pkt->ptype) {
2474 case DCERPC_PKT_RESPONSE:
2476 /* Here's where we deal with incoming sign/seal. */
2477 error = dcerpc_check_pdu_auth(state->call->sec,
2479 &pkt->u.response.stub_and_verifier,
2480 DCERPC_RESPONSE_LENGTH,
2482 if (!NT_STATUS_IS_OK(error)) {
2486 if (!state->got_first) {
2487 state->got_first = true;
2489 if (pkt->drep[0] & DCERPC_DREP_LE) {
2490 state->response.bigendian = false;
2492 state->response.bigendian = true;
2495 if (state->verify_bitmask1) {
2496 state->call->sec->verified_bitmask1 = true;
2499 if (state->verify_pcontext) {
2500 state->call->pres->verified_pcontext = true;
2504 if (state->response.bigendian) {
2505 if (pkt->drep[0] != 0) {
2506 return NT_STATUS_RPC_PROTOCOL_ERROR;
2509 if (pkt->drep[0] != DCERPC_DREP_LE) {
2510 return NT_STATUS_RPC_PROTOCOL_ERROR;
2513 if (pkt->drep[1] != 0) {
2514 return NT_STATUS_RPC_PROTOCOL_ERROR;
2516 if (pkt->drep[2] != 0) {
2517 return NT_STATUS_RPC_PROTOCOL_ERROR;
2519 if (pkt->drep[3] != 0) {
2520 return NT_STATUS_RPC_PROTOCOL_ERROR;
2523 if (pkt->u.response.context_id != state->call->pres->context_id) {
2524 return NT_STATUS_RPC_PROTOCOL_ERROR;
2527 if (frag.length < DCERPC_RESPONSE_LENGTH + pad_len) {
2528 return NT_STATUS_RPC_PROTOCOL_ERROR;
2531 /* Point the return values at the NDR data. */
2532 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
2534 if (pkt->auth_length) {
2535 /* We've already done integer wrap tests in
2536 * dcerpc_check_auth(). */
2537 payload.length = frag.length
2538 - DCERPC_RESPONSE_LENGTH
2540 - DCERPC_AUTH_TRAILER_LENGTH
2543 payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
2546 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
2547 (long unsigned int)frag.length,
2548 (long unsigned int)payload.length,
2549 (unsigned int)pad_len));
2552 * If this is the first reply, and the allocation hint is
2553 * reasonable, try and set up the reply_pdu DATA_BLOB to the
2557 if ((state->response.blob.length == 0) &&
2558 pkt->u.response.alloc_hint &&
2559 (pkt->u.response.alloc_hint < 15*1024*1024)) {
2560 ok = data_blob_realloc(state, &state->response.blob,
2561 pkt->u.response.alloc_hint);
2563 DEBUG(0, ("reply alloc hint %d too "
2564 "large to allocate\n",
2565 (int)pkt->u.response.alloc_hint));
2566 return NT_STATUS_NO_MEMORY;
2570 new_total = state->response.ofs + payload.length;
2572 if (new_total > 15 * 1024 *1024) {
2573 return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
2576 missing = new_total - state->response.blob.length;
2579 ok = data_blob_realloc(state, &state->response.blob,
2582 DEBUG(0, ("reply alloc hint %d too "
2583 "large to allocate\n",
2584 (int)pkt->u.response.alloc_hint));
2585 return NT_STATUS_NO_MEMORY;
2589 memcpy(state->response.blob.data + state->response.ofs,
2590 payload.data, payload.length);
2591 state->response.ofs += payload.length;
2593 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
2594 tevent_req_done(req);//TODO
2595 return NT_STATUS_OK;
2598 return dcerpc_connection_loop_restart(state->conn, state->ev);
2600 case DCERPC_PKT_FAULT:
2602 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
2603 "code %s received from %s!\n",
2604 dcerpc_errstr(talloc_tos(),
2605 pkt->u.fault.status),
2608 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
2609 if (NT_STATUS_IS_OK(status)) {
2610 status = NT_STATUS_RPC_PROTOCOL_ERROR;
2613 tevent_req_nterror(req, status);//TODO
2614 return NT_STATUS_OK;
2616 DEBUG(0, ("Unknown packet type %u received from %s!\n",
2617 (unsigned int)pkt->ptype,
2619 return NT_STATUS_RPC_PROTOCOL_ERROR;
2623 NTSTATUS dcerpc_do_request_recv(struct tevent_req *req,
2624 TALLOC_CTX *mem_ctx,
2625 DATA_BLOB *response,
2628 struct dcerpc_do_request_state *state =
2629 tevent_req_data(req,
2630 struct dcerpc_do_request_state);
2633 if (tevent_req_is_nterror(req, &status)) {
2634 tevent_req_received(req);
2638 /* return data to caller and assign it ownership of memory */
2639 response->data = talloc_move(mem_ctx, &state->response.blob.data);
2640 response->length = state->response.blob.length;
2641 *bigendian = state->response.bigendian;
2643 tevent_req_received(req);
2644 return NT_STATUS_OK;