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_context_handle;
41 struct dcerpc_association {
42 uint32_t assoc_group_id;
43 uint16_t client_features;
46 uint32_t next_call_id;
48 size_t num_context_handles;
49 struct db_context *context_handles;
52 struct dcerpc_connection {
53 struct dcerpc_association *assoc;
56 struct tstream_context *stream;
57 dcerpc_connection_use_trans_fn use_trans_fn;
58 struct tevent_queue *write_queue;
62 uint16_t max_xmit_frag;
63 uint16_t max_recv_frag;
64 bool concurrent_multiplex;
68 uint32_t next_sec_context_id;
69 uint16_t next_pres_context_id;
72 struct tevent_queue *out_queue;
73 struct dcerpc_call *list;
74 struct dcerpc_call *active;
75 struct dcerpc_call *new_call;
79 struct tevent_context *ev;
80 struct tevent_req *subreq;
84 struct dcerpc_security {
86 enum dcerpc_AuthType auth_type;
87 enum dcerpc_AuthLevel auth_level;
88 struct gensec_security *gensec;
89 struct auth_session_info *session_info;
90 DATA_BLOB session_key;
91 bool client_hdr_signing;
93 bool verified_bitmask1;
96 struct dcerpc_presentation {
98 const struct ndr_interface_table *table;
99 struct ndr_syntax_id transfer;
101 struct dcerpc_ctx_list req;
102 struct dcerpc_ack_ctx ack;
104 bool verified_pcontext;
108 struct dcerpc_call *prev, *next;
111 struct dcerpc_security *sec;
112 struct dcerpc_presentation *pres;
115 struct tevent_req *req;
116 NTSTATUS (*handler)(struct tevent_req *req,
117 struct ncacn_packet *pkt,
122 struct dcerpc_object_handle {
126 struct dcerpc_context_handle {
127 struct dcerpc_association *assoc;
129 struct policy_handle wire;
134 struct dcerpc_server_auth_info;
136 struct dcerpc_server {
142 struct dcerpc_server_auth_info {
143 struct dcerpc_server_auth_info *prev, *next;
144 enum dcerpc_AuthType auth_type;
145 enum dcerpc_AuthType min_auth_level;
146 const char *principal;
147 struct cli_credentials *creds;
150 struct dcerpc_server_manager {
151 const struct ndr_interface_table *table;
155 struct dcerpc_server_endpoint {
156 struct dcerpc_server_endpoint *prev, *next;
158 const struct dcerpc_binding *binding;
161 struct dcerpc_call_handle;
163 typedef struct tevent_req *(*dcerpc_call_entry_point_send_fn_t)(TALLOC_CTX *mem_ctx,
164 struct tevent_context *ev,
165 struct dcerpc_call_handle *call,
167 typedef NTSTATUS (*dcerpc_call_entry_point_recv_fn_t)(struct tevent_req *req);
169 struct dcerpc_call_entry_point_fns {
170 dcerpc_call_entry_point_send_fn_t fn_send;
171 dcerpc_call_entry_point_recv_fn_t fn_recv;
174 struct dcerpc_call_entry_point_vector {
176 const struct ndr_interface_table *table;
178 const struct dcerpc_call_entry_point_fns *fns;
181 struct dcerpc_association *dcerpc_association_create(TALLOC_CTX *mem_ctx,
182 uint16_t client_features)
184 struct dcerpc_association *assoc;
186 assoc = talloc_zero(mem_ctx, struct dcerpc_association);
191 assoc->next_call_id = 1;
193 assoc->client_features = client_features;
198 static int dcerpc_connection_destructor(struct dcerpc_connection *conn);
200 struct dcerpc_connection *dcerpc_connection_create(TALLOC_CTX *mem_ctx,
201 struct dcerpc_association *assoc,
202 struct tstream_context **stream)
204 struct dcerpc_connection *conn;
206 conn = talloc_zero(mem_ctx, struct dcerpc_connection);
212 conn->transport.stream = talloc_move(conn, stream);
213 conn->transport.write_queue = tevent_queue_create(conn, "write_queue");
214 if (conn->transport.write_queue == NULL) {
219 conn->features.max_xmit_frag = UINT16_MAX;
220 conn->features.max_recv_frag = UINT16_MAX;
222 conn->calls.out_queue = tevent_queue_create(conn, "out_queue");
223 if (conn->calls.out_queue == NULL) {
228 talloc_set_destructor(conn, dcerpc_connection_destructor);
233 void dcerpc_connection_set_max_fragment_sizes(struct dcerpc_connection *conn,
236 conn->features.max_xmit_frag = max_size;
237 conn->features.max_recv_frag = max_size;
240 void dcerpc_connection_set_use_trans_fn(struct dcerpc_connection *conn,
241 dcerpc_connection_use_trans_fn fn)
243 conn->transport.use_trans_fn = fn;
246 bool dcerpc_connection_is_connected(const struct dcerpc_connection *conn)
252 if (conn->transport.stream == NULL) {
259 static void dcerpc_connection_dead(struct dcerpc_connection *conn,
262 struct dcerpc_call *call = NULL;
268 if (conn->transport.stream == NULL) {
272 tevent_queue_stop(conn->transport.write_queue);
273 tevent_queue_stop(conn->calls.out_queue);
274 TALLOC_FREE(conn->loop.subreq);
275 TALLOC_FREE(conn->transport.stream);
277 if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, error)) {
278 error = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
281 if (NT_STATUS_EQUAL(NT_STATUS_OK, error)) {
282 error = NT_STATUS_LOCAL_DISCONNECT;
285 if (conn->calls.active != NULL) {
286 DLIST_PROMOTE(conn->calls.list, conn->calls.active);
289 if (conn->calls.new_call != NULL) {
290 DLIST_ADD_END(conn->calls.list, conn->calls.new_call, NULL);
291 conn->calls.new_call = NULL;
294 for (call = conn->calls.list; call; call = call->next) {
295 if (call->incoming.req == NULL) {
300 * the request was already prepared with
301 * tevent_req_defer_callback().
303 tevent_req_nterror(call->incoming.req, error);
307 static int dcerpc_connection_destructor(struct dcerpc_connection *conn)
309 dcerpc_connection_dead(conn, NT_STATUS_LOCAL_DISCONNECT);
313 struct dcerpc_security *dcerpc_security_allocate(
315 struct dcerpc_connection *conn,
316 enum dcerpc_AuthType auth_type,
317 enum dcerpc_AuthLevel auth_level,
318 struct gensec_security **gensec)
320 struct dcerpc_security *sec;
322 sec = talloc_zero(mem_ctx, struct dcerpc_security);
327 sec->context_id = conn->next_sec_context_id++;
328 sec->auth_type = auth_type;
329 sec->auth_level = auth_level;
331 if (gensec != NULL) {
332 sec->gensec = talloc_move(sec, gensec);
338 void dcerpc_security_get_auth_info(const struct dcerpc_security *sec,
339 enum dcerpc_AuthType *auth_type,
340 enum dcerpc_AuthLevel *auth_level)
342 enum dcerpc_AuthType _auth_type;
343 enum dcerpc_AuthLevel _auth_level;
345 if (auth_type == NULL) {
346 auth_type = &_auth_type;
349 if (auth_level == NULL) {
350 auth_level = &_auth_level;
354 *auth_type = DCERPC_AUTH_TYPE_NONE;
355 *auth_level = DCERPC_AUTH_LEVEL_NONE;
359 *auth_type = sec->auth_type;
360 *auth_level = sec->auth_level;
363 struct dcerpc_presentation *dcerpc_presentation_allocate(
365 struct dcerpc_connection *conn,
366 const struct ndr_interface_table *table,
367 const struct ndr_syntax_id *transfer)
369 struct dcerpc_presentation *pres;
371 pres = talloc_zero(mem_ctx, struct dcerpc_presentation);
376 pres->context_id = conn->next_pres_context_id++;
378 pres->transfer = *transfer;
380 pres->negotiate.req.abstract_syntax = table->syntax_id;
381 pres->negotiate.req.context_id = pres->context_id;
382 pres->negotiate.req.num_transfer_syntaxes = 1;
383 pres->negotiate.req.transfer_syntaxes = &pres->transfer;
385 pres->negotiate.ack.result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
386 pres->negotiate.ack.reason.value =
387 DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
392 struct dcerpc_presentation *dcerpc_presentation_test_copy(
394 const struct dcerpc_presentation *pres1,
395 const uint32_t *context_id,
396 const struct ndr_interface_table *table,
397 const struct ndr_syntax_id *transfer)
399 struct dcerpc_presentation *pres2;
401 pres2 = talloc_zero(mem_ctx, struct dcerpc_presentation);
407 if (context_id != NULL) {
408 pres2->context_id = *context_id;
411 pres2->table = table;
413 if (transfer != NULL) {
414 pres2->transfer = *transfer;
417 pres2->negotiate.req.abstract_syntax = pres2->table->syntax_id;
418 pres2->negotiate.req.context_id = pres2->context_id;
419 pres2->negotiate.req.num_transfer_syntaxes = 1;
420 pres2->negotiate.req.transfer_syntaxes = &pres2->transfer;
422 pres2->negotiate.ack.result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
423 pres2->negotiate.ack.reason.value =
424 DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
429 NTSTATUS dcerpc_presentation_status(const struct dcerpc_presentation *pres)
431 const struct dcerpc_ack_ctx *ack = &pres->negotiate.ack;
433 switch (ack->result) {
434 case DCERPC_BIND_ACK_RESULT_ACCEPTANCE:
437 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
439 * We have not asked for this...
441 return NT_STATUS_RPC_PROTOCOL_ERROR;
446 switch (ack->reason.value) {
447 case DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED:
448 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
450 case DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED:
451 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
457 return NT_STATUS_UNSUCCESSFUL;
460 struct dcerpc_call *dcerpc_call_allocate(TALLOC_CTX *mem_ctx,
461 struct dcerpc_association *assoc,
462 struct dcerpc_security *sec,
463 struct dcerpc_presentation *pres)
465 struct dcerpc_call *call;
467 call = talloc_zero(mem_ctx, struct dcerpc_call);
472 call->call_id = assoc->next_call_id++;
480 static NTSTATUS dcerpc_guess_pdu_sizes(struct dcerpc_security *sec,
483 size_t max_xmit_frag,
484 size_t pad_alignment,
485 size_t *data_to_send,
493 /* no auth token cases first */
494 switch (sec->auth_level) {
495 case DCERPC_AUTH_LEVEL_NONE:
496 case DCERPC_AUTH_LEVEL_CONNECT:
497 case DCERPC_AUTH_LEVEL_PACKET:
498 max_len = max_xmit_frag - header_len;
499 *data_to_send = MIN(max_len, data_left);
502 *frag_len = header_len + *data_to_send;
505 case DCERPC_AUTH_LEVEL_PRIVACY:
506 case DCERPC_AUTH_LEVEL_INTEGRITY:
507 if (sec->auth_type == DCERPC_AUTH_TYPE_NONE) {
508 return NT_STATUS_INVALID_PARAMETER_MIX;
510 if (sec->gensec == NULL) {
511 return NT_STATUS_INVALID_PARAMETER_MIX;
516 return NT_STATUS_INVALID_PARAMETER;
520 /* Sign/seal case, calculate auth and pad lengths */
522 max_len = max_xmit_frag - header_len - DCERPC_AUTH_TRAILER_LENGTH;
524 *auth_len = gensec_sig_size(sec->gensec, max_len);
526 max_len -= *auth_len;
528 *data_to_send = MIN(max_len, data_left);
530 mod_len = (*data_to_send) % pad_alignment;
532 *pad_len = pad_alignment - mod_len;
537 if (*data_to_send + *pad_len > max_len) {
538 *data_to_send -= pad_alignment;
541 *frag_len = header_len + *data_to_send + *pad_len
542 + DCERPC_AUTH_TRAILER_LENGTH + *auth_len;
547 static NTSTATUS dcerpc_ncacn_push_auth(DATA_BLOB *blob,
549 struct ncacn_packet *pkt,
550 struct dcerpc_auth *auth_info)
552 struct ndr_push *ndr;
553 enum ndr_err_code ndr_err;
555 ndr = ndr_push_init_ctx(mem_ctx);
557 return NT_STATUS_NO_MEMORY;
560 if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
561 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
564 if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
565 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
569 pkt->auth_length = auth_info->credentials.length;
571 // pkt->auth_length = 0;
574 ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
575 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
576 return ndr_map_error2ntstatus(ndr_err);
581 /* the s3 rpc server doesn't handle auth padding in
582 bind requests. Use zero auth padding to keep us
583 working with old servers */
584 uint32_t offset = ndr->offset;
585 ndr_err = ndr_push_align(ndr, 16);
586 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
587 return ndr_map_error2ntstatus(ndr_err);
589 auth_info->auth_pad_length = ndr->offset - offset;
591 auth_info->auth_pad_length = 0;
593 ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, auth_info);
594 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
595 return ndr_map_error2ntstatus(ndr_err);
599 *blob = ndr_push_blob(ndr);
601 /* fill in the frag length */
602 dcerpc_set_frag_length(blob, blob->length);
607 static NTSTATUS dcerpc_ncacn_packet_blob(TALLOC_CTX *mem_ctx,
608 enum dcerpc_pkt_type ptype,
610 uint16_t auth_length,
612 union dcerpc_payload *u,
615 struct ncacn_packet r;
619 r.rpc_vers_minor = 0;
621 r.pfc_flags = pfc_flags;
622 r.drep[0] = DCERPC_DREP_LE;
626 r.auth_length = auth_length;
630 status = dcerpc_ncacn_push_auth(blob, mem_ctx, &r, NULL);
631 if (!NT_STATUS_IS_OK(status)) {
635 if (DEBUGLEVEL >= 10) {
636 /* set frag len for print function */
637 r.frag_length = blob->length;
638 NDR_PRINT_DEBUG(ncacn_packet, &r);
644 #define DCERPC_PAYLOAD_PADDING_SIZE 16
646 static NTSTATUS dcerpc_auth_blob(TALLOC_CTX *mem_ctx,
647 enum dcerpc_AuthType auth_type,
648 enum dcerpc_AuthLevel auth_level,
649 uint8_t auth_pad_length,
650 uint32_t auth_context_id,
651 const DATA_BLOB *credentials,
654 struct dcerpc_auth r;
655 enum ndr_err_code ndr_err;
657 r.auth_type = auth_type;
658 r.auth_level = auth_level;
659 r.auth_pad_length = auth_pad_length;
661 r.auth_context_id = auth_context_id;
662 r.credentials = *credentials;
664 ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r,
665 (ndr_push_flags_fn_t)ndr_push_dcerpc_auth);
666 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
667 return ndr_map_error2ntstatus(ndr_err);
670 if (DEBUGLEVEL >= 10) {
671 NDR_PRINT_DEBUG(dcerpc_auth, &r);
677 static NTSTATUS dcerpc_response_auth_blob(struct dcerpc_security *sec,
682 char pad[DCERPC_PAYLOAD_PADDING_SIZE] = { 0, };
685 uint16_t data_and_pad_len = 0;
688 if (rpc_out->length < DCERPC_RESPONSE_LENGTH) {
689 return NT_STATUS_INVALID_PARAMETER_MIX;
692 if (sec->auth_type == DCERPC_AUTH_TYPE_NONE ||
693 sec->auth_type == DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM) {
697 if (sec->gensec == NULL) {
698 return NT_STATUS_INVALID_PARAMETER_MIX;
702 /* Copy the sign/seal padding data. */
703 if (!data_blob_append(NULL, rpc_out, pad, pad_len)) {
704 return NT_STATUS_NO_MEMORY;
708 data_and_pad_len = rpc_out->length - DCERPC_RESPONSE_LENGTH;
710 /* marshall the dcerpc_auth with an actually empty auth_blob.
711 * This is needed because the ntmlssp signature includes the
712 * auth header. We will append the actual blob later. */
713 auth_blob = data_blob_null;
714 status = dcerpc_auth_blob(rpc_out->data,
721 if (!NT_STATUS_IS_OK(status)) {
725 /* append the header */
726 if (!data_blob_append(NULL, rpc_out,
727 auth_info.data, auth_info.length)) {
728 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
729 (unsigned int)auth_info.length));
730 return NT_STATUS_NO_MEMORY;
732 data_blob_free(&auth_info);
734 switch (sec->auth_level) {
735 case DCERPC_AUTH_LEVEL_PRIVACY:
736 /* Data portion is encrypted. */
737 status = gensec_seal_packet(sec->gensec,
740 + DCERPC_RESPONSE_LENGTH,
745 if (!NT_STATUS_IS_OK(status)) {
750 case DCERPC_AUTH_LEVEL_INTEGRITY:
751 /* Data is signed. */
752 status = gensec_sign_packet(sec->gensec,
755 + DCERPC_RESPONSE_LENGTH,
760 if (!NT_STATUS_IS_OK(status)) {
767 smb_panic("bad auth level");
769 return NT_STATUS_INVALID_PARAMETER_MIX;
772 if (auth_blob.length != auth_len) {
773 return NT_STATUS_INVALID_PARAMETER_MIX;
776 /* Finally attach the blob. */
777 if (!data_blob_append(NULL, rpc_out,
778 auth_blob.data, auth_blob.length)) {
779 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
780 (unsigned int)auth_blob.length));
781 return NT_STATUS_NO_MEMORY;
783 data_blob_free(&auth_blob);
788 static NTSTATUS dcerpc_check_pdu_auth(struct dcerpc_security *sec,
789 struct ncacn_packet *pkt,
790 DATA_BLOB *pkt_trailer,
796 struct dcerpc_auth auth_info;
797 uint32_t auth_length;
801 switch (sec->auth_level) {
802 case DCERPC_AUTH_LEVEL_PRIVACY:
803 DEBUG(10, ("Requested Privacy.\n"));
806 case DCERPC_AUTH_LEVEL_INTEGRITY:
807 DEBUG(10, ("Requested Integrity.\n"));
810 case DCERPC_AUTH_LEVEL_CONNECT:
811 if (pkt->auth_length != 0) {
817 case DCERPC_AUTH_LEVEL_NONE:
818 if (pkt->auth_length != 0) {
819 DEBUG(3, ("Got non-zero auth len on non "
820 "authenticated connection!\n"));
821 return NT_STATUS_INVALID_PARAMETER;
827 DEBUG(3, ("Unimplemented Auth Level %d",
829 return NT_STATUS_INVALID_PARAMETER;
832 /* Paranioa checks for auth_length. */
833 if (pkt->auth_length > pkt->frag_length) {
834 return NT_STATUS_INFO_LENGTH_MISMATCH;
836 if (((unsigned int)pkt->auth_length
837 + DCERPC_AUTH_TRAILER_LENGTH < (unsigned int)pkt->auth_length) ||
838 ((unsigned int)pkt->auth_length
839 + DCERPC_AUTH_TRAILER_LENGTH < DCERPC_AUTH_TRAILER_LENGTH)) {
840 /* Integer wrap attempt. */
841 return NT_STATUS_INFO_LENGTH_MISMATCH;
844 status = dcerpc_pull_auth_trailer(pkt, pkt, pkt_trailer,
845 &auth_info, &auth_length, false);
846 if (!NT_STATUS_IS_OK(status)) {
850 if (auth_info.auth_type != sec->auth_type) {
851 return NT_STATUS_RPC_PROTOCOL_ERROR;
854 if (auth_info.auth_level != sec->auth_level) {
855 return NT_STATUS_RPC_PROTOCOL_ERROR;
858 if (auth_info.auth_context_id != sec->context_id) {
859 return NT_STATUS_RPC_PROTOCOL_ERROR;
862 data = data_blob_const(raw_pkt->data + header_size,
863 pkt_trailer->length - auth_length);
864 full_pkt = data_blob_const(raw_pkt->data,
865 raw_pkt->length - auth_info.credentials.length);
867 switch (sec->auth_type) {
868 case DCERPC_AUTH_TYPE_NONE:
869 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
875 switch (sec->auth_level) {
876 case DCERPC_AUTH_LEVEL_PRIVACY:
877 /* Data portion is encrypted. */
878 status = gensec_unseal_packet(sec->gensec,
883 &auth_info.credentials);
884 if (!NT_STATUS_IS_OK(status)) {
889 case DCERPC_AUTH_LEVEL_INTEGRITY:
890 /* Data is signed. */
891 status = gensec_check_packet(sec->gensec,
896 &auth_info.credentials);
897 if (!NT_STATUS_IS_OK(status)) {
902 return NT_STATUS_INVALID_PARAMETER;
904 /* TODO: remove later
905 * this is still needed because in the server code the
906 * pkt_trailer actually has a copy of the raw data, and they
907 * are still both used in later calls */
908 if (sec->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
909 memcpy(pkt_trailer->data, data.data, data.length);
912 *pad_len = auth_info.auth_pad_length;
913 data_blob_free(&auth_info.credentials);
917 static void dcerpc_connection_loop(struct tevent_req *subreq);
919 static NTSTATUS dcerpc_connection_loop_restart(struct dcerpc_connection *conn,
920 struct tevent_context *ev)
923 return NT_STATUS_INVALID_PARAMETER; // TODO...
926 if (conn->loop.subreq) {
927 if (conn->loop.ev != ev) {
928 return NT_STATUS_INVALID_PARAMETER; // TODO...
933 if (conn->calls.list == NULL) {
934 conn->loop.ev = NULL;
938 conn->loop.subreq = dcerpc_read_ncacn_packet_send(conn,
940 conn->transport.stream);
941 if (conn->loop.subreq == NULL) {
942 return NT_STATUS_NO_MEMORY;
944 tevent_req_set_callback(conn->loop.subreq, dcerpc_connection_loop, conn);
949 static void dcerpc_connection_loop(struct tevent_req *subreq)
951 struct dcerpc_connection *conn =
952 tevent_req_callback_data(subreq,
953 struct dcerpc_connection);
955 struct ncacn_packet *pkt;
957 struct dcerpc_call *call;
958 bool valid_type = false;
959 bool allow_fragments = false;
960 bool allow_newcall = false;
961 bool allow_ignore = false;
963 conn->loop.subreq = NULL;
965 error = dcerpc_read_ncacn_packet_recv(subreq, subreq, &pkt, &pdu);
966 if (!NT_STATUS_IS_OK(error)) {
968 dcerpc_connection_dead(conn, error);
972 if (DEBUGLEVEL >= 10) {
973 NDR_PRINT_DEBUG(ncacn_packet, pkt);
976 switch (pkt->ptype) {
977 case DCERPC_PKT_REQUEST:
978 /* Ordinary request. */
980 allow_fragments = true;
981 allow_newcall = true;
984 case DCERPC_PKT_PING:
985 /* Connectionless is server alive ? */
988 case DCERPC_PKT_RESPONSE:
989 /* Ordinary reply. */
991 allow_fragments = true;
994 case DCERPC_PKT_FAULT:
995 /* Fault in processing of call. */
999 case DCERPC_PKT_WORKING:
1000 /* Connectionless reply to a ping when server busy. */
1003 case DCERPC_PKT_NOCALL:
1004 /* Connectionless reply to a ping when server has lost part of clients call. */
1007 case DCERPC_PKT_REJECT:
1008 /* Refuse a request with a code. */
1011 case DCERPC_PKT_ACK:
1014 case DCERPC_PKT_CL_CANCEL:
1017 case DCERPC_PKT_FACK:
1020 case DCERPC_PKT_CANCEL_ACK:
1021 /* Server ACK to client cancel request. */
1024 case DCERPC_PKT_BIND:
1025 /* Bind to interface. */
1027 allow_newcall = true;
1030 case DCERPC_PKT_BIND_ACK:
1031 /* Server ack of bind. */
1035 case DCERPC_PKT_BIND_NAK:
1036 /* Server nack of bind. */
1040 case DCERPC_PKT_ALTER:
1043 allow_newcall = true;
1046 case DCERPC_PKT_ALTER_RESP:
1047 /* Reply to alter auth. */
1051 case DCERPC_PKT_AUTH3:
1054 allow_newcall = true;
1057 case DCERPC_PKT_SHUTDOWN:
1058 /* Server to client request to shutdown. */
1062 case DCERPC_PKT_CO_CANCEL:
1063 /* Connection-oriented cancel request. */
1065 allow_ignore = true;
1068 case DCERPC_PKT_ORPHANED:
1070 * Client telling server it's aborting a partially sent request
1071 * or telling server to stop sending replies.
1074 allow_ignore = true;
1077 case DCERPC_PKT_RTS:
1078 /* RTS packets used in ncacn_http */
1083 TALLOC_FREE(subreq);
1084 dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1088 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1089 if (!allow_fragments) {
1090 TALLOC_FREE(subreq);
1091 dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1096 if (conn->calls.active != NULL) {
1098 if (pkt->call_id != conn->calls.active->call_id) {
1099 TALLOC_FREE(subreq);
1100 dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1104 if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) {
1105 TALLOC_FREE(subreq);
1106 dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1110 call = conn->calls.active;
1112 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1113 conn->calls.active = NULL;
1116 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1117 TALLOC_FREE(subreq);
1118 dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1122 call = conn->calls.list;
1125 for (call = conn->calls.list; call; call = call->next) {
1126 if (call->call_id == pkt->call_id) {
1131 if (call == NULL && allow_newcall) {
1132 call = conn->calls.new_call;
1135 if (call == NULL && allow_ignore) {
1136 TALLOC_FREE(subreq);
1141 TALLOC_FREE(subreq);
1142 dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1146 if (call->incoming.handler == NULL) {
1147 TALLOC_FREE(subreq);
1148 dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1152 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1153 conn->calls.active = call;
1157 // reassemble and return
1160 error = call->incoming.handler(call->incoming.req, pkt, pdu);
1161 TALLOC_FREE(subreq);
1162 if (!NT_STATUS_IS_OK(error)) {
1163 dcerpc_connection_dead(conn, error);
1168 if (conn->calls.new_call == NULL) {
1169 conn->loop.ev = NULL;
1173 error = dcerpc_connection_loop_restart(conn, conn->loop.ev);
1174 if (!NT_STATUS_IS_OK(error)) {
1175 dcerpc_connection_dead(conn, error);
1180 struct dcerpc_do_bind_out_frag;
1182 struct dcerpc_do_bind_state {
1183 struct tevent_context *ev;
1184 struct dcerpc_connection *conn;
1185 struct dcerpc_call *call;
1186 struct dcerpc_security *sec;
1187 bool proposed_hdr_signing;
1189 NTSTATUS sec_status;
1191 struct dcerpc_do_bind_out_frag *out_frag;
1193 struct dcerpc_presentation **pres;
1194 uint32_t remaining_pres;
1197 struct dcerpc_ctx_list *ctx_list;
1198 struct ndr_syntax_id features;
1201 struct dcerpc_do_bind_out_frag {
1202 struct tevent_context *ev;
1203 struct dcerpc_connection *conn;
1204 struct tevent_req *req;
1205 enum dcerpc_pkt_type ptype;
1207 struct iovec vector;
1208 struct tevent_req *subreq_wait1;
1209 struct tevent_req *subreq_wait2;
1212 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
1213 enum tevent_req_state req_state);
1215 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq);
1216 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq);
1218 static NTSTATUS dcerpc_do_bind_handle_in_frag(struct tevent_req *req,
1219 struct ncacn_packet *pkt,
1222 struct tevent_req *dcerpc_do_bind_send(TALLOC_CTX *mem_ctx,
1223 struct tevent_context *ev,
1224 struct dcerpc_connection *conn,
1225 struct dcerpc_call *call,
1226 struct dcerpc_security *sec,
1228 struct dcerpc_presentation **pres)
1230 struct tevent_req *req;
1231 struct dcerpc_do_bind_state *state;
1232 struct tevent_req *subreq;
1234 req = tevent_req_create(mem_ctx, &state,
1235 struct dcerpc_do_bind_state);
1243 state->remaining_pres = num_pres;
1244 state->num_pres = num_pres;
1247 state->call->incoming.req = req;
1248 state->call->incoming.handler = dcerpc_do_bind_handle_in_frag;
1249 DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
1250 tevent_req_defer_callback(req, ev);
1251 tevent_req_set_cleanup_fn(req, dcerpc_do_bind_cleanup);
1253 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1254 subreq = gensec_update_send(state, ev,
1257 if (tevent_req_nomem(subreq, req)) {
1258 return tevent_req_post(req, ev);
1260 tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
1265 state->sec_status = NT_STATUS_OK;
1267 subreq = tevent_queue_wait_send(state, state->ev,
1268 state->conn->calls.out_queue);
1269 if (tevent_req_nomem(subreq, req)) {
1270 return tevent_req_post(req, ev);
1272 tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
1277 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
1278 enum tevent_req_state req_state)
1280 struct dcerpc_do_bind_state *state =
1281 tevent_req_data(req,
1282 struct dcerpc_do_bind_state);
1284 if (state->out_frag != NULL) {
1285 state->out_frag->req = NULL;
1286 state->out_frag = NULL;
1289 if (state->call != NULL) {
1290 if (state->call == state->conn->calls.active) {
1291 state->conn->calls.active = NULL;
1293 ZERO_STRUCT(state->call->incoming);
1294 DLIST_REMOVE(state->conn->calls.list, state->call);
1299 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq)
1301 struct tevent_req *req =
1302 tevent_req_callback_data(subreq,
1304 struct dcerpc_do_bind_state *state =
1305 tevent_req_data(req,
1306 struct dcerpc_do_bind_state);
1309 data_blob_free(&state->sec_out);
1310 status = gensec_update_recv(subreq, state, &state->sec_out);
1311 TALLOC_FREE(subreq);
1312 data_blob_free(&state->sec_in);
1313 state->sec_status = status;
1314 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1315 status = NT_STATUS_OK;
1317 if (!NT_STATUS_IS_OK(status)) {
1318 tevent_req_nterror(req, status);
1322 if (NT_STATUS_IS_OK(state->sec_status) &&
1323 state->sec_out.length == 0)
1325 tevent_req_done(req);
1329 if (state->sec->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1330 state->sec->client_hdr_signing =
1331 gensec_have_feature(state->sec->gensec,
1332 GENSEC_FEATURE_SIGN_PKT_HEADER);
1335 subreq = tevent_queue_wait_send(state, state->ev,
1336 state->conn->calls.out_queue);
1337 if (tevent_req_nomem(subreq, req)) {
1340 tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
1343 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq);
1344 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq);
1345 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq);
1347 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq)
1349 struct tevent_req *req =
1350 tevent_req_callback_data(subreq,
1352 struct dcerpc_do_bind_state *state =
1353 tevent_req_data(req,
1354 struct dcerpc_do_bind_state);
1355 struct dcerpc_do_bind_out_frag *frag;
1356 size_t auth_len = 0;
1358 DATA_BLOB auth_info = data_blob_null;
1359 uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1360 union dcerpc_payload u;
1362 bool require_ack = false;
1363 bool use_trans = true;
1366 ok = tevent_queue_wait_recv(subreq);
1368 //status = NT_STATUS_INTERNAL_ERROR;
1369 tevent_req_oom(req);
1372 TALLOC_FREE(subreq);
1375 * the fragment belongs to the connection instead of the request
1376 * because it has to remain in case the request is canceled
1378 frag = talloc_zero(state->conn, struct dcerpc_do_bind_out_frag);
1379 if (tevent_req_nomem(frag, req)) {
1382 frag->ev = state->ev;
1383 frag->conn = state->conn;
1385 state->out_frag = frag;
1387 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1388 if (state->sec->client_hdr_signing &&
1389 !state->proposed_hdr_signing)
1391 state->proposed_hdr_signing = true;
1392 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1397 //TODO : DCERPC_PFC_FLAG_CONC_MPX
1399 //TODO: remaining_pres
1401 if (!state->conn->features.bind_done) {
1402 frag->ptype = DCERPC_PKT_BIND;
1403 } else if (require_ack) {
1404 frag->ptype = DCERPC_PKT_ALTER;
1405 } else if (state->remaining_pres > 0) {
1406 frag->ptype = DCERPC_PKT_ALTER;
1407 } else if (!NT_STATUS_IS_OK(state->sec_status)) {
1408 frag->ptype = DCERPC_PKT_ALTER;
1410 frag->ptype = DCERPC_PKT_AUTH3;
1413 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1414 status = dcerpc_auth_blob(frag,
1415 state->sec->auth_type,
1416 state->sec->auth_level,
1417 0, /* auth_pad_length */
1418 state->sec->context_id, /* auth_context_id */
1421 if (!NT_STATUS_IS_OK(status)) {
1422 tevent_req_nterror(req, status);
1426 auth_len = auth_info.length;
1429 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1433 state->num_ctx = state->num_pres;
1434 if (!state->conn->assoc->negotiate_done) {
1435 state->num_ctx += 1;
1438 state->ctx_list = talloc_zero_array(frag,
1439 struct dcerpc_ctx_list,
1441 if (tevent_req_nomem(state->ctx_list, req)) {
1445 for (i=0; i < state->num_pres; i++) {
1446 state->ctx_list[i] = state->pres[i]->negotiate.req;
1449 if (!state->conn->assoc->negotiate_done) {
1450 state->features = dcerpc_construct_bind_time_features(
1451 state->conn->assoc->client_features);
1453 state->ctx_list[i].context_id = state->conn->next_pres_context_id;
1455 state->ctx_list[i].abstract_syntax =
1456 state->ctx_list[i-1].abstract_syntax;
1458 state->ctx_list[i].num_transfer_syntaxes = 1;
1459 state->ctx_list[i].transfer_syntaxes = &state->features;
1462 switch (frag->ptype) {
1463 case DCERPC_PKT_BIND:
1464 case DCERPC_PKT_ALTER:
1465 u.bind.max_xmit_frag = state->conn->features.max_xmit_frag;
1466 u.bind.max_recv_frag = state->conn->features.max_recv_frag;
1467 u.bind.assoc_group_id = state->conn->assoc->assoc_group_id;
1468 u.bind.num_contexts = state->num_ctx;
1469 u.bind.ctx_list = state->ctx_list;
1470 u.bind.auth_info = auth_info;
1473 case DCERPC_PKT_AUTH3:
1475 u.auth3.auth_info = auth_info;
1478 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1482 status = dcerpc_ncacn_packet_blob(frag,
1486 state->call->call_id,
1489 if (!NT_STATUS_IS_OK(status)) {
1490 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1491 tevent_req_nterror(req, status);
1495 if (frag->ptype == DCERPC_PKT_AUTH3) {
1499 if (frag->conn->transport.use_trans_fn == NULL) {
1503 if (frag->conn->loop.subreq != NULL) {
1507 if (frag->conn->features.concurrent_multiplex) {
1511 if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
1516 frag->subreq_wait1 = tevent_queue_wait_send(frag,
1518 frag->conn->transport.write_queue);
1519 if (tevent_req_nomem(req, frag->subreq_wait1)) {
1522 tevent_req_set_callback(frag->subreq_wait1,
1523 dcerpc_do_bind_out_frag_trans_wait1,
1526 * we need to block reads until our write is
1527 * the next in the write queue.
1529 frag->conn->loop.subreq = frag->subreq_wait1;
1530 frag->conn->loop.ev = frag->ev;
1534 * We need to add a dcerpc_write_fragment_queue_send/recv()
1537 frag->vector.iov_base = frag->blob.data;
1538 frag->vector.iov_len = frag->blob.length;
1539 subreq = tstream_writev_queue_send(frag, frag->ev,
1540 frag->conn->transport.stream,
1541 frag->conn->transport.write_queue,
1543 if (tevent_req_nomem(subreq, req)) {
1546 tevent_req_set_callback(subreq,
1547 dcerpc_do_bind_out_frag_done,
1551 frag->subreq_wait2 = tevent_queue_wait_send(frag,
1553 frag->conn->transport.write_queue);
1554 if (tevent_req_nomem(req, frag->subreq_wait2)) {
1557 tevent_req_set_callback(frag->subreq_wait2,
1558 dcerpc_do_bind_out_frag_trans_wait2,
1562 if (frag->ptype == DCERPC_PKT_AUTH3) {
1566 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1567 if (tevent_req_nterror(req, status)) {
1572 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq)
1574 struct dcerpc_do_bind_out_frag *frag =
1575 tevent_req_callback_data(subreq,
1576 struct dcerpc_do_bind_out_frag);
1577 struct dcerpc_connection *conn = frag->conn;
1583 * TODO; what if the caller has been free'ed?
1584 * TALLOC_FREE(frag->subreq_write)
1587 frag->subreq_wait1 = NULL;
1588 conn->loop.subreq = NULL;
1590 ok = tevent_queue_wait_recv(subreq);
1593 dcerpc_connection_dead(conn, NT_STATUS_INTERNAL_ERROR);
1597 if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
1599 * We added 3 entries into the queue,
1600 * wait1, writev and wait2.
1602 * There's more to write, we should not block
1603 * further writev calls for a trans call.
1605 * The wait2 stage will trigger the read.
1607 TALLOC_FREE(subreq);
1612 * we don't need wait2 anymore, we're sure that
1613 * we'll do a trans call.
1615 TALLOC_FREE(frag->subreq_wait2);
1617 status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
1618 if (!NT_STATUS_IS_OK(status)) {
1620 dcerpc_connection_dead(conn, status);
1624 /* we free subreq after tstream_cli_np_use_trans */
1625 TALLOC_FREE(subreq);
1627 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1628 if (!NT_STATUS_IS_OK(status)) {
1630 dcerpc_connection_dead(conn, status);
1635 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq)
1637 struct dcerpc_do_bind_out_frag *frag =
1638 tevent_req_callback_data(subreq,
1639 struct dcerpc_do_bind_out_frag);
1640 struct dcerpc_connection *conn = frag->conn;
1641 struct tevent_req *req = frag->req;
1647 * If the caller has been free'ed, we have should
1648 * ignore any errors and just free 'frag'
1651 struct dcerpc_do_bind_state *state =
1652 tevent_req_data(req,
1653 struct dcerpc_do_bind_state);
1655 state->out_frag = NULL;
1658 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1659 TALLOC_FREE(subreq);
1662 status = map_nt_error_from_unix_common(sys_errno);
1663 dcerpc_connection_dead(conn, status);
1667 if (frag->ptype == DCERPC_PKT_AUTH3) {
1672 tevent_req_done(req);
1676 if (frag->subreq_wait2 != NULL) {
1682 /* we need to wait for incoming pdus */
1685 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq)
1687 struct dcerpc_do_bind_out_frag *frag =
1688 tevent_req_callback_data(subreq,
1689 struct dcerpc_do_bind_out_frag);
1690 struct dcerpc_connection *conn = frag->conn;
1694 frag->subreq_wait2 = NULL;
1696 ok = tevent_queue_wait_recv(subreq);
1699 dcerpc_connection_dead(conn, NT_STATUS_INTERNAL_ERROR);
1703 TALLOC_FREE(subreq);
1705 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1706 if (!NT_STATUS_IS_OK(status)) {
1708 dcerpc_connection_dead(conn, status);
1714 /* we need to wait for incoming pdus */
1717 static NTSTATUS dcerpc_do_bind_handle_in_frag(struct tevent_req *req,
1718 struct ncacn_packet *pkt,
1721 struct dcerpc_do_bind_state *state =
1722 tevent_req_data(req,
1723 struct dcerpc_do_bind_state);
1725 struct dcerpc_presentation *last_pres = NULL;
1726 size_t num_pres_ok = 0;
1729 /* Ensure we have the correct type. */
1730 switch (pkt->ptype) {
1731 case DCERPC_PKT_BIND_ACK:
1732 case DCERPC_PKT_ALTER_RESP:
1733 if (!state->conn->features.bind_done) {
1734 if (pkt->u.bind_ack.max_recv_frag < 1234) {
1735 return NT_STATUS_RPC_PROTOCOL_ERROR;
1737 if (pkt->u.bind_ack.max_xmit_frag < 1234) {
1738 return NT_STATUS_RPC_PROTOCOL_ERROR;
1740 state->conn->features.max_recv_frag =
1741 pkt->u.bind_ack.max_recv_frag;
1742 state->conn->features.max_xmit_frag =
1743 pkt->u.bind_ack.max_xmit_frag;
1745 if (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) {
1746 state->conn->features.concurrent_multiplex = true;
1749 state->conn->features.bind_done = true;
1752 if (!state->conn->assoc->negotiate_done) {
1753 state->conn->assoc->negotiate_done = true;
1754 state->conn->assoc->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
1757 if (pkt->u.bind_ack.assoc_group_id != state->conn->assoc->assoc_group_id) {
1758 return NT_STATUS_RPC_PROTOCOL_ERROR;
1761 if (pkt->u.bind_ack.num_results > state->num_ctx) {
1762 return NT_STATUS_RPC_PROTOCOL_ERROR;
1765 state->remaining_pres = 0;
1767 if (state->proposed_hdr_signing) {
1768 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1769 state->sec->hdr_signing = true;
1773 for (i = 0; i < pkt->u.bind_ack.num_results; i++) {
1774 struct dcerpc_ack_ctx *ack = &pkt->u.bind_ack.ctx_list[i];
1776 if (i < state->num_pres) {
1777 struct dcerpc_ack_ctx *pack =
1778 &state->pres[i]->negotiate.ack;
1780 if (ack->result == DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1781 return NT_STATUS_RPC_PROTOCOL_ERROR;
1784 if (ack->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1790 if (pack->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1792 * if a presentation context was valid it must
1793 * be valid for the lifetime of the connection
1795 return NT_STATUS_RPC_PROTOCOL_ERROR;
1799 last_pres = state->pres[i];
1803 if (ack->result != DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1807 state->conn->assoc->features = state->conn->assoc->client_features;
1808 state->conn->assoc->features &= ack->reason.negotiate;
1811 for (i = 0; i < state->num_pres; i++) {
1812 struct dcerpc_ack_ctx *ack = &state->pres[i]->negotiate.ack;
1815 if (ack->result != DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1819 ok = ndr_syntax_id_equal(&state->pres[i]->transfer,
1822 return NT_STATUS_RPC_PROTOCOL_ERROR;
1826 if (num_pres_ok == 0 && last_pres != NULL) {
1827 status = dcerpc_presentation_status(last_pres);
1828 tevent_req_nterror(req, status);
1829 return NT_STATUS_OK;
1832 if (pkt->auth_length >= 8) {
1833 struct tevent_req *subreq;
1835 state->sec_in = data_blob_talloc(state,
1836 pkt->u.bind_ack.auth_info.data + 8,
1837 pkt->u.bind_ack.auth_info.length - 8);
1839 subreq = gensec_update_send(state, state->ev,
1842 if (tevent_req_nomem(subreq, req)) {
1843 return NT_STATUS_OK;
1845 tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
1846 return NT_STATUS_OK;
1849 tevent_req_done(req);
1850 return NT_STATUS_OK;
1852 //case DCERPC_PKT_ALTER_RESP:
1853 if (pkt->auth_length != 0) {
1854 return NT_STATUS_NOT_IMPLEMENTED;
1857 return NT_STATUS_NOT_IMPLEMENTED;
1860 /* Point the return values at the NDR data. */
1861 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
1863 if (pkt->auth_length) {
1864 /* We've already done integer wrap tests in
1865 * dcerpc_check_auth(). */
1866 payload.length = frag.length
1867 - DCERPC_RESPONSE_LENGTH
1869 - DCERPC_AUTH_TRAILER_LENGTH
1872 payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
1875 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1876 if (pkt->drep[0] & DCERPC_DREP_LE) {
1877 state->response.bigendian = false;
1879 state->response.bigendian = true;
1883 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
1884 (long unsigned int)frag.length,
1885 (long unsigned int)payload.length,
1886 (unsigned int)pad_len));
1889 * If this is the first reply, and the allocation hint is
1890 * reasonable, try and set up the reply_pdu DATA_BLOB to the
1894 if ((state->response.blob.length == 0) &&
1895 pkt->u.response.alloc_hint &&
1896 (pkt->u.response.alloc_hint < 15*1024*1024)) {
1897 ok = data_blob_realloc(state, &state->response.blob,
1898 pkt->u.response.alloc_hint);
1900 DEBUG(0, ("reply alloc hint %d too "
1901 "large to allocate\n",
1902 (int)pkt->u.response.alloc_hint));
1903 return NT_STATUS_NO_MEMORY;
1907 new_total = state->response.ofs + payload.length;
1909 if (new_total > 15 * 1024 *1024) {
1910 return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
1913 missing = new_total - state->response.blob.length;
1916 ok = data_blob_realloc(state, &state->response.blob,
1919 DEBUG(0, ("reply alloc hint %d too "
1920 "large to allocate\n",
1921 (int)pkt->u.response.alloc_hint));
1922 return NT_STATUS_NO_MEMORY;
1926 memcpy(state->response.blob.data + state->response.ofs,
1927 payload.data, payload.length);
1928 state->response.ofs += payload.length;
1930 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1931 tevent_req_done(req);//TODO
1932 return NT_STATUS_OK;
1934 return NT_STATUS_OK;
1936 return NT_STATUS_NOT_IMPLEMENTED;
1938 case DCERPC_PKT_FAULT:
1940 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1941 "code %s received from %s!\n",
1942 dcerpc_errstr(talloc_tos(),
1943 pkt->u.fault.status),
1946 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
1947 if (NT_STATUS_IS_OK(status)) {
1948 status = NT_STATUS_RPC_PROTOCOL_ERROR;
1951 tevent_req_nterror(req, status);//TODO
1952 return NT_STATUS_OK;
1954 DEBUG(0, ("Unknown packet type %u received from %s!\n",
1955 (unsigned int)pkt->ptype,
1957 return NT_STATUS_RPC_PROTOCOL_ERROR;
1960 return NT_STATUS_RPC_PROTOCOL_ERROR;
1963 NTSTATUS dcerpc_do_bind_recv(struct tevent_req *req)
1965 struct dcerpc_do_bind_state *state =
1966 tevent_req_data(req,
1967 struct dcerpc_do_bind_state);
1970 if (tevent_req_is_nterror(req, &status)) {
1971 tevent_req_received(req);
1975 if (!NT_STATUS_IS_OK(state->sec_status)) {
1976 status = state->sec_status;
1977 tevent_req_received(req);
1981 tevent_req_received(req);
1982 return NT_STATUS_OK;
1985 struct dcerpc_do_request_out_frag;
1987 struct dcerpc_do_request_state {
1988 struct tevent_context *ev;
1989 struct dcerpc_connection *conn;
1990 struct dcerpc_call *call;
1991 const struct GUID *object;
1994 const DATA_BLOB *blob;
2000 bool verify_bitmask1;
2001 bool verify_pcontext;
2003 struct dcerpc_do_request_out_frag *out_frag;
2011 struct dcerpc_do_request_out_frag {
2012 struct tevent_context *ev;
2013 struct dcerpc_connection *conn;
2014 struct tevent_req *req;
2017 struct iovec vector;
2018 struct tevent_req *subreq_wait1;
2019 struct tevent_req *subreq_wait2;
2022 static void dcerpc_do_request_cleanup(struct tevent_req *req,
2023 enum tevent_req_state req_state);
2025 static void dcerpc_do_request_verification_trailer(struct tevent_req *req);
2026 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
2027 void *private_data);
2029 static NTSTATUS dcerpc_do_request_handle_in_frag(struct tevent_req *req,
2030 struct ncacn_packet *pkt,
2033 struct tevent_req *dcerpc_do_request_send(TALLOC_CTX *mem_ctx,
2034 struct tevent_context *ev,
2035 struct dcerpc_connection *conn,
2036 struct dcerpc_call *call,
2037 const struct GUID *object,
2039 const DATA_BLOB *request,
2042 struct tevent_req *req;
2043 struct dcerpc_do_request_state *state;
2046 req = tevent_req_create(mem_ctx, &state,
2047 struct dcerpc_do_request_state);
2054 state->object = object;
2055 state->opnum = opnum;
2056 state->request.blob = request;
2057 state->request.bigendian = bigendian;
2059 dcerpc_do_request_verification_trailer(req);
2060 if (!tevent_req_is_in_progress(req)) {
2061 return tevent_req_post(req, ev);
2064 state->call->incoming.req = req;
2065 state->call->incoming.handler = dcerpc_do_request_handle_in_frag;
2066 DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
2067 tevent_req_defer_callback(req, ev);
2068 tevent_req_set_cleanup_fn(req, dcerpc_do_request_cleanup);
2070 ok = tevent_queue_add(state->conn->calls.out_queue,
2073 dcerpc_do_request_out_frag_next,
2076 tevent_req_nomem(NULL, req);
2077 return tevent_req_post(req, ev);
2083 static void dcerpc_do_request_cleanup(struct tevent_req *req,
2084 enum tevent_req_state req_state)
2086 struct dcerpc_do_request_state *state =
2087 tevent_req_data(req,
2088 struct dcerpc_do_request_state);
2090 if (state->out_frag != NULL) {
2091 state->out_frag->req = NULL;
2092 state->out_frag = NULL;
2095 if (state->call != NULL) {
2096 if (state->call == state->conn->calls.active) {
2097 state->conn->calls.active = NULL;
2099 ZERO_STRUCT(state->call->incoming);
2100 DLIST_REMOVE(state->conn->calls.list, state->call);
2105 static void dcerpc_do_request_verification_trailer(struct tevent_req *req)
2107 struct dcerpc_do_request_state *state =
2108 tevent_req_data(req,
2109 struct dcerpc_do_request_state);
2110 struct dcerpc_sec_verification_trailer *t;
2111 struct dcerpc_sec_vt *c = NULL;
2112 struct ndr_push *ndr = NULL;
2113 enum ndr_err_code ndr_err;
2117 if (state->call->sec->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
2121 t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
2122 if (tevent_req_nomem(t, req)) {
2126 if (!state->call->sec->verified_bitmask1) {
2127 t->commands = talloc_realloc(t, t->commands,
2128 struct dcerpc_sec_vt,
2129 t->count.count + 1);
2130 if (tevent_req_nomem(t->commands, req)) {
2133 c = &t->commands[t->count.count++];
2136 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
2137 if (state->call->sec->client_hdr_signing) {
2138 c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
2140 state->verify_bitmask1 = true;
2143 if (!state->call->pres->verified_pcontext) {
2144 t->commands = talloc_realloc(t, t->commands,
2145 struct dcerpc_sec_vt,
2146 t->count.count + 1);
2147 if (tevent_req_nomem(t->commands, req)) {
2150 c = &t->commands[t->count.count++];
2153 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
2154 c->u.pcontext.abstract_syntax = state->call->pres->table->syntax_id;
2155 c->u.pcontext.transfer_syntax = state->call->pres->transfer;
2157 state->verify_pcontext = true;
2160 if (!state->call->sec->hdr_signing) {
2161 t->commands = talloc_realloc(t, t->commands,
2162 struct dcerpc_sec_vt,
2163 t->count.count + 1);
2164 if (tevent_req_nomem(t->commands, req)) {
2167 c = &t->commands[t->count.count++];
2170 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
2171 c->u.header2.ptype = DCERPC_PKT_REQUEST;
2172 if (state->request.bigendian) {
2173 c->u.header2.drep[0] = 0;
2175 c->u.header2.drep[0] = DCERPC_DREP_LE;
2177 c->u.header2.drep[1] = 0;
2178 c->u.header2.drep[2] = 0;
2179 c->u.header2.drep[3] = 0;
2180 c->u.header2.call_id = state->call->call_id;
2181 c->u.header2.context_id = 0;
2182 c->u.header2.opnum = state->opnum;
2185 if (t->count.count == 0) {
2190 c = &t->commands[t->count.count - 1];
2191 c->command |= DCERPC_SEC_VT_COMMAND_END;
2193 if (DEBUGLEVEL >= 10) {
2194 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
2197 ndr = ndr_push_init_ctx(state);
2198 if (tevent_req_nomem(ndr, req)) {
2202 //TODO if (state->request.bigendian)
2204 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
2205 NDR_SCALARS | NDR_BUFFERS,
2207 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2208 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2209 tevent_req_nterror(req, status);
2212 state->request.trailer = ndr_push_blob(ndr);
2214 align = state->request.blob->length & 0x3;
2221 const uint8_t zeros[4] = { 0, };
2223 ok = data_blob_append(ndr, &state->request.trailer, zeros, pad);
2225 tevent_req_oom(req);
2229 /* move the padding to the start */
2230 p = state->request.trailer.data;
2231 memmove(p + pad, p, state->request.trailer.length - pad);
2238 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq);
2239 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq);
2240 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq);
2242 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
2245 struct dcerpc_do_request_state *state =
2246 tevent_req_data(req,
2247 struct dcerpc_do_request_state);
2248 struct dcerpc_do_request_out_frag *frag;
2249 size_t hdr_len = DCERPC_REQUEST_LENGTH;
2255 size_t data_thistime;
2256 size_t trailer_left;
2257 size_t trailer_thistime = 0;
2259 size_t total_thistime;
2261 union dcerpc_payload u;
2263 struct tevent_req *subreq;
2264 bool use_trans = true;
2266 if (state->object) {
2267 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
2272 * the fragment belongs to the connection instead of the request
2273 * because it has to remain in case the request is canceled
2275 frag = talloc_zero(state->conn, struct dcerpc_do_request_out_frag);
2276 if (tevent_req_nomem(frag, req)) {
2279 frag->ev = state->ev;
2280 frag->conn = state->conn;
2282 state->out_frag = frag;
2284 data_left = state->request.blob->length - state->request.ofs;
2285 trailer_left = state->request.trailer.length - state->request.trailer_ofs;
2286 total_left = data_left + trailer_left;
2287 if (total_left < data_left || total_left < trailer_left) {
2288 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2292 status = dcerpc_guess_pdu_sizes(state->call->sec,
2293 hdr_len, total_left,
2294 state->conn->features.max_xmit_frag,
2295 DCERPC_PAYLOAD_PADDING_SIZE,
2297 &frag_len, &auth_len, &pad_len);
2298 if (!NT_STATUS_IS_OK(status)) {
2299 tevent_req_nterror(req, status);
2303 if (state->request.ofs == 0) {
2304 flags |= DCERPC_PFC_FLAG_FIRST;
2307 if (total_thistime == total_left) {
2308 flags |= DCERPC_PFC_FLAG_LAST;
2311 data_thistime = MIN(total_thistime, data_left);
2312 if (data_thistime < total_thistime) {
2313 trailer_thistime = total_thistime - data_thistime;
2316 ZERO_STRUCT(u.request);
2318 u.request.alloc_hint = total_left;
2319 u.request.context_id = state->call->pres->context_id;
2320 u.request.opnum = state->opnum;
2321 if (state->object) {
2322 u.request.object.object = *state->object;
2324 //TODO pass state->request.bigendian
2325 status = dcerpc_ncacn_packet_blob(frag,
2329 state->call->call_id,
2332 if (!NT_STATUS_IS_OK(status)) {
2333 tevent_req_nterror(req, status);
2337 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2338 * compute it right for requests because the auth trailer is missing
2340 dcerpc_set_frag_length(&frag->blob, frag_len);
2342 if (data_thistime > 0) {
2343 const uint8_t *data_ptr;
2345 data_ptr = state->request.blob->data;
2346 data_ptr += state->request.ofs;
2348 /* Copy in the data. */
2349 ok = data_blob_append(frag, &frag->blob,
2350 data_ptr, data_thistime);
2352 tevent_req_oom(req);
2356 state->request.ofs += data_thistime;
2359 if (trailer_thistime > 0) {
2360 const uint8_t *trailer_ptr;
2362 trailer_ptr = state->request.trailer.data;
2363 trailer_ptr += state->request.trailer_ofs;
2365 /* Copy in the data. */
2366 ok = data_blob_append(frag, &frag->blob,
2367 trailer_ptr, trailer_thistime);
2369 tevent_req_oom(req);
2373 state->request.trailer_ofs += trailer_thistime;
2376 switch (state->call->sec->auth_level) {
2377 case DCERPC_AUTH_LEVEL_NONE:
2378 case DCERPC_AUTH_LEVEL_CONNECT:
2379 case DCERPC_AUTH_LEVEL_PACKET:
2381 case DCERPC_AUTH_LEVEL_INTEGRITY:
2382 case DCERPC_AUTH_LEVEL_PRIVACY:
2383 status = dcerpc_response_auth_blob(state->call->sec,
2387 if (!NT_STATUS_IS_OK(status)) {
2388 tevent_req_nterror(req, status);
2393 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2397 frag->is_last = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2399 if (!frag->is_last) {
2403 if (frag->conn->transport.use_trans_fn == NULL) {
2407 if (frag->conn->loop.subreq != NULL) {
2411 if (frag->conn->features.concurrent_multiplex) {
2415 if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
2420 frag->subreq_wait1 = tevent_queue_wait_send(frag,
2422 frag->conn->transport.write_queue);
2423 if (tevent_req_nomem(req, frag->subreq_wait1)) {
2426 tevent_req_set_callback(frag->subreq_wait1,
2427 dcerpc_do_request_out_frag_trans_wait1,
2430 * we need to block reads until our write is
2431 * the next in the write queue.
2433 frag->conn->loop.subreq = frag->subreq_wait1;
2434 frag->conn->loop.ev = frag->ev;
2438 * We need to add a dcerpc_write_fragment_queue_send/recv()
2441 frag->vector.iov_base = frag->blob.data;
2442 frag->vector.iov_len = frag->blob.length;
2443 subreq = tstream_writev_queue_send(frag, frag->ev,
2444 frag->conn->transport.stream,
2445 frag->conn->transport.write_queue,
2447 if (tevent_req_nomem(subreq, req)) {
2450 tevent_req_set_callback(subreq,
2451 dcerpc_do_request_out_frag_done,
2455 frag->subreq_wait2 = tevent_queue_wait_send(frag,
2457 frag->conn->transport.write_queue);
2458 if (tevent_req_nomem(req, frag->subreq_wait2)) {
2461 tevent_req_set_callback(frag->subreq_wait2,
2462 dcerpc_do_request_out_frag_trans_wait2,
2466 if (!frag->is_last) {
2470 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2471 if (tevent_req_nterror(req, status)) {
2476 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq)
2478 struct dcerpc_do_request_out_frag *frag =
2479 tevent_req_callback_data(subreq,
2480 struct dcerpc_do_request_out_frag);
2481 struct tevent_req *req = frag->req;
2486 * TODO; what if the caller has been free'ed?
2489 frag->subreq_wait1 = NULL;
2490 frag->conn->loop.subreq = NULL;
2492 ok = tevent_queue_wait_recv(subreq);
2494 status = NT_STATUS_INTERNAL_ERROR;
2497 tevent_req_nterror(req, status);
2499 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2503 if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
2505 * We added 3 entries into the queue,
2506 * wait1, writev and wait2.
2508 * There's more to write, we should not block
2509 * further writev calls for a trans call.
2511 * The wait2 stage will trigger the read.
2513 TALLOC_FREE(subreq);
2518 * we don't need wait2 anymore, we're sure that
2519 * we'll do a trans call.
2521 TALLOC_FREE(frag->subreq_wait2);
2523 status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
2524 if (!NT_STATUS_IS_OK(status)) {
2527 tevent_req_nterror(req, status);
2529 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2533 /* we free subreq after tstream_cli_np_use_trans */
2534 TALLOC_FREE(subreq);
2536 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2537 if (!NT_STATUS_IS_OK(status)) {
2540 tevent_req_nterror(req, status);
2542 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2547 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq)
2549 struct dcerpc_do_request_out_frag *frag =
2550 tevent_req_callback_data(subreq,
2551 struct dcerpc_do_request_out_frag);
2552 struct tevent_req *req = frag->req;
2558 * If the caller has been free'ed, we have should
2559 * ignore any errors and just free 'frag'
2562 struct dcerpc_do_request_state *state =
2563 tevent_req_data(req,
2564 struct dcerpc_do_request_state);
2566 state->out_frag = NULL;
2569 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2570 TALLOC_FREE(subreq);
2573 status = map_nt_error_from_unix_common(sys_errno);
2575 tevent_req_nterror(req, status);
2580 if (frag->subreq_wait2 != NULL) {
2584 if (frag->is_last) {
2594 dcerpc_do_request_out_frag_next(req, NULL);
2597 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq)
2599 struct dcerpc_do_request_out_frag *frag =
2600 tevent_req_callback_data(subreq,
2601 struct dcerpc_do_request_out_frag);
2602 struct tevent_req *req = frag->req;
2606 frag->subreq_wait2 = NULL;
2608 ok = tevent_queue_wait_recv(subreq);
2610 status = NT_STATUS_INTERNAL_ERROR;
2613 tevent_req_nterror(req, status);
2615 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2619 TALLOC_FREE(subreq);
2621 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2622 if (!NT_STATUS_IS_OK(status)) {
2625 tevent_req_nterror(req, status);
2627 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2633 /* we need to wait for incoming pdus */
2636 static NTSTATUS dcerpc_do_request_handle_in_frag(struct tevent_req *req,
2637 struct ncacn_packet *pkt,
2640 struct dcerpc_do_request_state *state =
2641 tevent_req_data(req,
2642 struct dcerpc_do_request_state);
2651 /* Ensure we have the correct type. */
2652 switch (pkt->ptype) {
2653 case DCERPC_PKT_RESPONSE:
2655 /* Here's where we deal with incoming sign/seal. */
2656 error = dcerpc_check_pdu_auth(state->call->sec,
2658 &pkt->u.response.stub_and_verifier,
2659 DCERPC_RESPONSE_LENGTH,
2661 if (!NT_STATUS_IS_OK(error)) {
2665 if (!state->got_first) {
2666 state->got_first = true;
2668 if (pkt->drep[0] & DCERPC_DREP_LE) {
2669 state->response.bigendian = false;
2671 state->response.bigendian = true;
2674 if (state->verify_bitmask1) {
2675 state->call->sec->verified_bitmask1 = true;
2678 if (state->verify_pcontext) {
2679 state->call->pres->verified_pcontext = true;
2683 if (state->response.bigendian) {
2684 if (pkt->drep[0] != 0) {
2685 return NT_STATUS_RPC_PROTOCOL_ERROR;
2688 if (pkt->drep[0] != DCERPC_DREP_LE) {
2689 return NT_STATUS_RPC_PROTOCOL_ERROR;
2692 if (pkt->drep[1] != 0) {
2693 return NT_STATUS_RPC_PROTOCOL_ERROR;
2695 if (pkt->drep[2] != 0) {
2696 return NT_STATUS_RPC_PROTOCOL_ERROR;
2698 if (pkt->drep[3] != 0) {
2699 return NT_STATUS_RPC_PROTOCOL_ERROR;
2702 if (pkt->u.response.context_id != state->call->pres->context_id) {
2703 return NT_STATUS_RPC_PROTOCOL_ERROR;
2706 if (frag.length < DCERPC_RESPONSE_LENGTH + pad_len) {
2707 return NT_STATUS_RPC_PROTOCOL_ERROR;
2710 /* Point the return values at the NDR data. */
2711 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
2713 if (pkt->auth_length) {
2714 /* We've already done integer wrap tests in
2715 * dcerpc_check_auth(). */
2716 payload.length = frag.length
2717 - DCERPC_RESPONSE_LENGTH
2719 - DCERPC_AUTH_TRAILER_LENGTH
2722 payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
2725 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
2726 (long unsigned int)frag.length,
2727 (long unsigned int)payload.length,
2728 (unsigned int)pad_len));
2731 * If this is the first reply, and the allocation hint is
2732 * reasonable, try and set up the reply_pdu DATA_BLOB to the
2736 if ((state->response.blob.length == 0) &&
2737 pkt->u.response.alloc_hint &&
2738 (pkt->u.response.alloc_hint < 15*1024*1024)) {
2739 ok = data_blob_realloc(state, &state->response.blob,
2740 pkt->u.response.alloc_hint);
2742 DEBUG(0, ("reply alloc hint %d too "
2743 "large to allocate\n",
2744 (int)pkt->u.response.alloc_hint));
2745 return NT_STATUS_NO_MEMORY;
2749 new_total = state->response.ofs + payload.length;
2751 if (new_total > 15 * 1024 *1024) {
2752 return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
2755 missing = new_total - state->response.blob.length;
2758 ok = data_blob_realloc(state, &state->response.blob,
2761 DEBUG(0, ("reply alloc hint %d too "
2762 "large to allocate\n",
2763 (int)pkt->u.response.alloc_hint));
2764 return NT_STATUS_NO_MEMORY;
2768 memcpy(state->response.blob.data + state->response.ofs,
2769 payload.data, payload.length);
2770 state->response.ofs += payload.length;
2772 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
2773 tevent_req_done(req);//TODO
2774 return NT_STATUS_OK;
2777 return dcerpc_connection_loop_restart(state->conn, state->ev);
2779 case DCERPC_PKT_FAULT:
2781 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
2782 "code %s received from %s!\n",
2783 dcerpc_errstr(talloc_tos(),
2784 pkt->u.fault.status),
2787 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
2788 if (NT_STATUS_IS_OK(status)) {
2789 status = NT_STATUS_RPC_PROTOCOL_ERROR;
2792 tevent_req_nterror(req, status);//TODO
2793 return NT_STATUS_OK;
2795 DEBUG(0, ("Unknown packet type %u received from %s!\n",
2796 (unsigned int)pkt->ptype,
2798 return NT_STATUS_RPC_PROTOCOL_ERROR;
2802 NTSTATUS dcerpc_do_request_recv(struct tevent_req *req,
2803 TALLOC_CTX *mem_ctx,
2804 DATA_BLOB *response,
2807 struct dcerpc_do_request_state *state =
2808 tevent_req_data(req,
2809 struct dcerpc_do_request_state);
2812 if (tevent_req_is_nterror(req, &status)) {
2813 tevent_req_received(req);
2817 /* return data to caller and assign it ownership of memory */
2818 response->data = talloc_move(mem_ctx, &state->response.blob.data);
2819 response->length = state->response.blob.length;
2820 *bigendian = state->response.bigendian;
2822 tevent_req_received(req);
2823 return NT_STATUS_OK;
2826 struct dcerpc_submit_fault_frag {
2828 struct iovec vector;
2831 static void dcerpc_submit_fault_done(struct tevent_req *subreq);
2833 static NTSTATUS dcerpc_submit_fault(struct dcerpc_connection *conn,
2834 struct tevent_context *ev,
2836 uint32_t context_id,
2839 struct dcerpc_submit_fault_frag *frag;
2841 union dcerpc_payload u;
2842 struct tevent_req *subreq;
2844 if (!dcerpc_connection_is_connected(conn)) {
2845 return NT_STATUS_OK;
2849 * the fragment belongs to the connection instead of the request
2850 * because it has to remain in case the request is canceled
2852 frag = talloc_zero(conn, struct dcerpc_submit_fault_frag);
2854 return NT_STATUS_NO_MEMORY;
2857 ZERO_STRUCT(u.fault);
2858 u.fault.context_id = context_id;
2859 u.fault.status = dcerpc_fault_from_nt_status(nt_status);
2861 error = dcerpc_ncacn_packet_blob(frag,
2863 DCERPC_PFC_FLAG_FIRST |
2864 DCERPC_PFC_FLAG_LAST,
2869 if (!NT_STATUS_IS_OK(error)) {
2874 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2875 * compute it right for requests because the auth trailer is missing
2877 //dcerpc_set_frag_length(&frag->blob, frag_len);
2880 * We need to add a dcerpc_write_fragment_queue_send/recv()
2883 frag->vector.iov_base = frag->blob.data;
2884 frag->vector.iov_len = frag->blob.length;
2885 subreq = tstream_writev_queue_send(frag, ev,
2886 conn->transport.stream,
2887 conn->transport.write_queue,
2889 if (subreq == NULL) {
2891 return NT_STATUS_NO_MEMORY;
2893 tevent_req_set_callback(subreq,
2894 dcerpc_submit_fault_done,
2897 return NT_STATUS_OK;
2900 static void dcerpc_submit_fault_done(struct tevent_req *subreq)
2902 struct dcerpc_submit_fault_frag *frag =
2903 tevent_req_callback_data(subreq,
2904 struct dcerpc_submit_fault_frag);
2906 TALLOC_FREE(subreq);
2911 struct dcerpc_submit_shutdown_frag {
2912 struct dcerpc_connection *conn;
2914 struct iovec vector;
2917 static void dcerpc_submit_shutdown_done(struct tevent_req *subreq);
2919 static NTSTATUS dcerpc_submit_shutdown(struct dcerpc_connection *conn,
2920 struct tevent_context *ev)
2922 struct dcerpc_submit_shutdown_frag *frag;
2924 union dcerpc_payload u;
2925 struct tevent_req *subreq;
2927 if (!dcerpc_connection_is_connected(conn)) {
2928 return NT_STATUS_OK;
2931 TALLOC_FREE(conn->loop.subreq);
2934 * the fragment belongs to the connection instead of the request
2935 * because it has to remain in case the request is canceled
2937 frag = talloc_zero(conn, struct dcerpc_submit_shutdown_frag);
2939 return NT_STATUS_NO_MEMORY;
2943 ZERO_STRUCT(u.shutdown);
2945 error = dcerpc_ncacn_packet_blob(frag,
2946 DCERPC_PKT_SHUTDOWN,
2947 DCERPC_PFC_FLAG_FIRST |
2948 DCERPC_PFC_FLAG_LAST,
2949 0, /* auth_length */
2953 if (!NT_STATUS_IS_OK(error)) {
2958 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2959 * compute it right for requests because the auth trailer is missing
2961 //dcerpc_set_frag_length(&frag->blob, frag_len);
2964 * We need to add a dcerpc_write_fragment_queue_send/recv()
2967 frag->vector.iov_base = frag->blob.data;
2968 frag->vector.iov_len = frag->blob.length;
2969 subreq = tstream_writev_queue_send(frag, ev,
2970 conn->transport.stream,
2971 conn->transport.write_queue,
2973 if (subreq == NULL) {
2975 return NT_STATUS_NO_MEMORY;
2977 tevent_req_set_callback(subreq,
2978 dcerpc_submit_shutdown_done,
2981 conn->loop.subreq = subreq;
2983 return NT_STATUS_OK;
2986 static void dcerpc_submit_shutdown_done(struct tevent_req *subreq)
2988 struct dcerpc_submit_shutdown_frag *frag =
2989 tevent_req_callback_data(subreq,
2990 struct dcerpc_submit_shutdown_frag);
2991 struct dcerpc_connection *conn = frag->conn;
2993 TALLOC_FREE(subreq);
2997 dcerpc_connection_dead(conn, NT_STATUS_LOCAL_DISCONNECT);
3000 struct dcerpc_server_connection_loop_state {
3001 struct tevent_context *ev;
3002 struct dcerpc_connection *conn;
3004 struct dcerpc_server *server;
3006 struct dcerpc_server_association *assoc;
3008 uint32_t last_call_id;
3010 bool allow_incoming;
3013 struct db_context *secs;
3016 struct db_context *pres;
3019 static void dcerpc_server_connection_loop_cleanup(struct tevent_req *req,
3020 enum tevent_req_state req_state);
3022 static NTSTATUS dcerpc_server_connection_loop_handle_in_frag(struct tevent_req *req,
3023 struct ncacn_packet *pkt,
3026 struct tevent_req *dcerpc_server_connection_loop_send(TALLOC_CTX *mem_ctx,
3027 struct tevent_context *ev,
3028 struct dcerpc_connection *conn,
3029 struct dcerpc_server *server)
3031 struct tevent_req *req;
3032 struct dcerpc_server_connection_loop_state *state;
3033 struct dcerpc_call *call;
3035 req = tevent_req_create(mem_ctx, &state,
3036 struct dcerpc_server_connection_loop_state);
3043 if (state->conn->calls.new_call != NULL) {
3044 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
3045 return tevent_req_post(req, ev);
3048 call = talloc_zero(state, struct dcerpc_call);
3053 call->incoming.req = req;
3054 call->incoming.handler = dcerpc_server_connection_loop_handle_in_frag;
3055 conn->calls.new_call = call;
3056 tevent_req_defer_callback(req, ev);
3057 tevent_req_set_cleanup_fn(req, dcerpc_server_connection_loop_cleanup);
3059 state->allow_incoming = true;
3060 //TODO different dcerpc_connection_dead() behavior as server?
3065 static void dcerpc_server_connection_loop_cleanup(struct tevent_req *req,
3066 enum tevent_req_state req_state)
3068 struct dcerpc_server_connection_loop_state *state =
3069 tevent_req_data(req,
3070 struct dcerpc_server_connection_loop_state);
3072 state->allow_incoming = false;
3074 if (state->conn != NULL) {
3075 TALLOC_FREE(state->conn->calls.new_call);
3080 static NTSTATUS dcerpc_server_connection_loop_handle_in_frag(struct tevent_req *req,
3081 struct ncacn_packet *pkt,
3084 struct dcerpc_server_connection_loop_state *state =
3085 tevent_req_data(req,
3086 struct dcerpc_server_connection_loop_state);
3088 if (!state->allow_incoming) {
3089 DEBUG(0, ("Unexpected packet type %u received from %s!\n",
3090 (unsigned int)pkt->ptype,
3092 return NT_STATUS_RPC_PROTOCOL_ERROR;
3095 /* Ensure we have the correct type. */
3096 switch (pkt->ptype) {
3097 case DCERPC_PKT_BIND:
3098 if (state->conn->features.bind_done) {
3099 return NT_STATUS_RPC_PROTOCOL_ERROR;
3101 state->allow_incoming = false;
3104 case DCERPC_PKT_AUTH3:
3105 if (!state->conn->features.bind_done) {
3106 return NT_STATUS_RPC_PROTOCOL_ERROR;
3110 case DCERPC_PKT_ALTER:
3111 if (!state->conn->features.bind_done) {
3112 return NT_STATUS_RPC_PROTOCOL_ERROR;
3116 case DCERPC_PKT_REQUEST:
3117 if (!state->conn->features.bind_done) {
3118 return NT_STATUS_RPC_PROTOCOL_ERROR;
3122 case DCERPC_PKT_CO_CANCEL:
3123 case DCERPC_PKT_ORPHANED:
3126 DEBUG(0, ("Unknown packet type %u received from %s!\n",
3127 (unsigned int)pkt->ptype,
3129 return NT_STATUS_RPC_PROTOCOL_ERROR;
3132 // TODO check last_call_id range, here or in the main loop???
3134 /* Ensure we have the correct type. */
3135 switch (pkt->ptype) {
3136 case DCERPC_PKT_BIND:
3139 state->conn->features.bind_done = true;
3140 state->allow_incoming = true;
3143 case DCERPC_PKT_AUTH3:
3148 case DCERPC_PKT_ALTER:
3153 case DCERPC_PKT_REQUEST:
3159 return NT_STATUS_INTERNAL_ERROR;
3162 return NT_STATUS_NOT_IMPLEMENTED;
3165 NTSTATUS dcerpc_server_connection_loop_recv(struct tevent_req *req)
3167 return tevent_req_simple_recv_ntstatus(req);