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_server_auth_info;
124 struct dcerpc_server {
130 struct dcerpc_server_auth_info {
131 struct dcerpc_server_auth_info *prev, *next;
132 enum dcerpc_AuthType auth_type;
133 enum dcerpc_AuthType min_auth_level;
134 const char *principal;
135 struct cli_credentials *creds;
138 struct dcerpc_server_endpoint {
139 struct dcerpc_server_endpoint *prev, *next;
143 struct dcerpc_context_handle {
144 struct dcerpc_association *assoc;
146 struct policy_handle wire;
151 struct dcerpc_association *dcerpc_association_create(TALLOC_CTX *mem_ctx,
152 uint16_t client_features)
154 struct dcerpc_association *assoc;
156 assoc = talloc_zero(mem_ctx, struct dcerpc_association);
161 assoc->next_call_id = 1;
163 assoc->client_features = client_features;
168 static int dcerpc_connection_destructor(struct dcerpc_connection *conn);
170 struct dcerpc_connection *dcerpc_connection_create(TALLOC_CTX *mem_ctx,
171 struct dcerpc_association *assoc,
172 struct tstream_context **stream)
174 struct dcerpc_connection *conn;
176 conn = talloc_zero(mem_ctx, struct dcerpc_connection);
182 conn->transport.stream = talloc_move(conn, stream);
183 conn->transport.write_queue = tevent_queue_create(conn, "write_queue");
184 if (conn->transport.write_queue == NULL) {
189 conn->features.max_xmit_frag = UINT16_MAX;
190 conn->features.max_recv_frag = UINT16_MAX;
192 conn->calls.out_queue = tevent_queue_create(conn, "out_queue");
193 if (conn->calls.out_queue == NULL) {
198 talloc_set_destructor(conn, dcerpc_connection_destructor);
203 void dcerpc_connection_set_max_fragment_sizes(struct dcerpc_connection *conn,
206 conn->features.max_xmit_frag = max_size;
207 conn->features.max_recv_frag = max_size;
210 void dcerpc_connection_set_use_trans_fn(struct dcerpc_connection *conn,
211 dcerpc_connection_use_trans_fn fn)
213 conn->transport.use_trans_fn = fn;
216 bool dcerpc_connection_is_connected(const struct dcerpc_connection *conn)
222 if (conn->transport.stream == NULL) {
229 static void dcerpc_connection_dead(struct dcerpc_connection *conn,
232 struct dcerpc_call *call = NULL;
238 if (conn->transport.stream == NULL) {
242 tevent_queue_stop(conn->transport.write_queue);
243 tevent_queue_stop(conn->calls.out_queue);
244 TALLOC_FREE(conn->loop.subreq);
245 TALLOC_FREE(conn->transport.stream);
247 if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, error)) {
248 error = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
251 if (NT_STATUS_EQUAL(NT_STATUS_OK, error)) {
252 error = NT_STATUS_LOCAL_DISCONNECT;
255 if (conn->calls.active != NULL) {
256 DLIST_PROMOTE(conn->calls.list, conn->calls.active);
259 if (conn->calls.new_call != NULL) {
260 DLIST_ADD_END(conn->calls.list, conn->calls.new_call, NULL);
261 conn->calls.new_call = NULL;
264 for (call = conn->calls.list; call; call = call->next) {
265 if (call->incoming.req == NULL) {
270 * the request was already prepared with
271 * tevent_req_defer_callback().
273 tevent_req_nterror(call->incoming.req, error);
277 static int dcerpc_connection_destructor(struct dcerpc_connection *conn)
279 dcerpc_connection_dead(conn, NT_STATUS_LOCAL_DISCONNECT);
283 struct dcerpc_security *dcerpc_security_allocate(
285 struct dcerpc_connection *conn,
286 enum dcerpc_AuthType auth_type,
287 enum dcerpc_AuthLevel auth_level,
288 struct gensec_security **gensec)
290 struct dcerpc_security *sec;
292 sec = talloc_zero(mem_ctx, struct dcerpc_security);
297 sec->context_id = conn->next_sec_context_id++;
298 sec->auth_type = auth_type;
299 sec->auth_level = auth_level;
301 if (gensec != NULL) {
302 sec->gensec = talloc_move(sec, gensec);
308 void dcerpc_security_get_auth_info(const struct dcerpc_security *sec,
309 enum dcerpc_AuthType *auth_type,
310 enum dcerpc_AuthLevel *auth_level)
312 enum dcerpc_AuthType _auth_type;
313 enum dcerpc_AuthLevel _auth_level;
315 if (auth_type == NULL) {
316 auth_type = &_auth_type;
319 if (auth_level == NULL) {
320 auth_level = &_auth_level;
324 *auth_type = DCERPC_AUTH_TYPE_NONE;
325 *auth_level = DCERPC_AUTH_LEVEL_NONE;
329 *auth_type = sec->auth_type;
330 *auth_level = sec->auth_level;
333 struct dcerpc_presentation *dcerpc_presentation_allocate(
335 struct dcerpc_connection *conn,
336 const struct ndr_interface_table *table,
337 const struct ndr_syntax_id *transfer)
339 struct dcerpc_presentation *pres;
341 pres = talloc_zero(mem_ctx, struct dcerpc_presentation);
346 pres->context_id = conn->next_pres_context_id++;
348 pres->transfer = *transfer;
350 pres->negotiate.req.abstract_syntax = table->syntax_id;
351 pres->negotiate.req.context_id = pres->context_id;
352 pres->negotiate.req.num_transfer_syntaxes = 1;
353 pres->negotiate.req.transfer_syntaxes = &pres->transfer;
355 pres->negotiate.ack.result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
356 pres->negotiate.ack.reason.value =
357 DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
362 struct dcerpc_presentation *dcerpc_presentation_test_copy(
364 const struct dcerpc_presentation *pres1,
365 const uint32_t *context_id,
366 const struct ndr_interface_table *table,
367 const struct ndr_syntax_id *transfer)
369 struct dcerpc_presentation *pres2;
371 pres2 = talloc_zero(mem_ctx, struct dcerpc_presentation);
377 if (context_id != NULL) {
378 pres2->context_id = *context_id;
381 pres2->table = table;
383 if (transfer != NULL) {
384 pres2->transfer = *transfer;
387 pres2->negotiate.req.abstract_syntax = pres2->table->syntax_id;
388 pres2->negotiate.req.context_id = pres2->context_id;
389 pres2->negotiate.req.num_transfer_syntaxes = 1;
390 pres2->negotiate.req.transfer_syntaxes = &pres2->transfer;
392 pres2->negotiate.ack.result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
393 pres2->negotiate.ack.reason.value =
394 DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
399 NTSTATUS dcerpc_presentation_status(const struct dcerpc_presentation *pres)
401 const struct dcerpc_ack_ctx *ack = &pres->negotiate.ack;
403 switch (ack->result) {
404 case DCERPC_BIND_ACK_RESULT_ACCEPTANCE:
407 case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
409 * We have not asked for this...
411 return NT_STATUS_RPC_PROTOCOL_ERROR;
416 switch (ack->reason.value) {
417 case DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED:
418 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
420 case DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED:
421 return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
427 return NT_STATUS_UNSUCCESSFUL;
430 struct dcerpc_call *dcerpc_call_allocate(TALLOC_CTX *mem_ctx,
431 struct dcerpc_association *assoc,
432 struct dcerpc_security *sec,
433 struct dcerpc_presentation *pres)
435 struct dcerpc_call *call;
437 call = talloc_zero(mem_ctx, struct dcerpc_call);
442 call->call_id = assoc->next_call_id++;
450 static NTSTATUS dcerpc_guess_pdu_sizes(struct dcerpc_security *sec,
453 size_t max_xmit_frag,
454 size_t pad_alignment,
455 size_t *data_to_send,
463 /* no auth token cases first */
464 switch (sec->auth_level) {
465 case DCERPC_AUTH_LEVEL_NONE:
466 case DCERPC_AUTH_LEVEL_CONNECT:
467 case DCERPC_AUTH_LEVEL_PACKET:
468 max_len = max_xmit_frag - header_len;
469 *data_to_send = MIN(max_len, data_left);
472 *frag_len = header_len + *data_to_send;
475 case DCERPC_AUTH_LEVEL_PRIVACY:
476 case DCERPC_AUTH_LEVEL_INTEGRITY:
477 if (sec->auth_type == DCERPC_AUTH_TYPE_NONE) {
478 return NT_STATUS_INVALID_PARAMETER_MIX;
480 if (sec->gensec == NULL) {
481 return NT_STATUS_INVALID_PARAMETER_MIX;
486 return NT_STATUS_INVALID_PARAMETER;
490 /* Sign/seal case, calculate auth and pad lengths */
492 max_len = max_xmit_frag - header_len - DCERPC_AUTH_TRAILER_LENGTH;
494 *auth_len = gensec_sig_size(sec->gensec, max_len);
496 max_len -= *auth_len;
498 *data_to_send = MIN(max_len, data_left);
500 mod_len = (*data_to_send) % pad_alignment;
502 *pad_len = pad_alignment - mod_len;
507 if (*data_to_send + *pad_len > max_len) {
508 *data_to_send -= pad_alignment;
511 *frag_len = header_len + *data_to_send + *pad_len
512 + DCERPC_AUTH_TRAILER_LENGTH + *auth_len;
517 static NTSTATUS dcerpc_ncacn_push_auth(DATA_BLOB *blob,
519 struct ncacn_packet *pkt,
520 struct dcerpc_auth *auth_info)
522 struct ndr_push *ndr;
523 enum ndr_err_code ndr_err;
525 ndr = ndr_push_init_ctx(mem_ctx);
527 return NT_STATUS_NO_MEMORY;
530 if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
531 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
534 if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
535 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
539 pkt->auth_length = auth_info->credentials.length;
541 // pkt->auth_length = 0;
544 ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
545 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
546 return ndr_map_error2ntstatus(ndr_err);
551 /* the s3 rpc server doesn't handle auth padding in
552 bind requests. Use zero auth padding to keep us
553 working with old servers */
554 uint32_t offset = ndr->offset;
555 ndr_err = ndr_push_align(ndr, 16);
556 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
557 return ndr_map_error2ntstatus(ndr_err);
559 auth_info->auth_pad_length = ndr->offset - offset;
561 auth_info->auth_pad_length = 0;
563 ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, auth_info);
564 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
565 return ndr_map_error2ntstatus(ndr_err);
569 *blob = ndr_push_blob(ndr);
571 /* fill in the frag length */
572 dcerpc_set_frag_length(blob, blob->length);
577 static NTSTATUS dcerpc_ncacn_packet_blob(TALLOC_CTX *mem_ctx,
578 enum dcerpc_pkt_type ptype,
580 uint16_t auth_length,
582 union dcerpc_payload *u,
585 struct ncacn_packet r;
589 r.rpc_vers_minor = 0;
591 r.pfc_flags = pfc_flags;
592 r.drep[0] = DCERPC_DREP_LE;
596 r.auth_length = auth_length;
600 status = dcerpc_ncacn_push_auth(blob, mem_ctx, &r, NULL);
601 if (!NT_STATUS_IS_OK(status)) {
605 if (DEBUGLEVEL >= 10) {
606 /* set frag len for print function */
607 r.frag_length = blob->length;
608 NDR_PRINT_DEBUG(ncacn_packet, &r);
614 #define DCERPC_PAYLOAD_PADDING_SIZE 16
616 static NTSTATUS dcerpc_auth_blob(TALLOC_CTX *mem_ctx,
617 enum dcerpc_AuthType auth_type,
618 enum dcerpc_AuthLevel auth_level,
619 uint8_t auth_pad_length,
620 uint32_t auth_context_id,
621 const DATA_BLOB *credentials,
624 struct dcerpc_auth r;
625 enum ndr_err_code ndr_err;
627 r.auth_type = auth_type;
628 r.auth_level = auth_level;
629 r.auth_pad_length = auth_pad_length;
631 r.auth_context_id = auth_context_id;
632 r.credentials = *credentials;
634 ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r,
635 (ndr_push_flags_fn_t)ndr_push_dcerpc_auth);
636 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
637 return ndr_map_error2ntstatus(ndr_err);
640 if (DEBUGLEVEL >= 10) {
641 NDR_PRINT_DEBUG(dcerpc_auth, &r);
647 static NTSTATUS dcerpc_response_auth_blob(struct dcerpc_security *sec,
652 char pad[DCERPC_PAYLOAD_PADDING_SIZE] = { 0, };
655 uint16_t data_and_pad_len = 0;
658 if (rpc_out->length < DCERPC_RESPONSE_LENGTH) {
659 return NT_STATUS_INVALID_PARAMETER_MIX;
662 if (sec->auth_type == DCERPC_AUTH_TYPE_NONE ||
663 sec->auth_type == DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM) {
667 if (sec->gensec == NULL) {
668 return NT_STATUS_INVALID_PARAMETER_MIX;
672 /* Copy the sign/seal padding data. */
673 if (!data_blob_append(NULL, rpc_out, pad, pad_len)) {
674 return NT_STATUS_NO_MEMORY;
678 data_and_pad_len = rpc_out->length - DCERPC_RESPONSE_LENGTH;
680 /* marshall the dcerpc_auth with an actually empty auth_blob.
681 * This is needed because the ntmlssp signature includes the
682 * auth header. We will append the actual blob later. */
683 auth_blob = data_blob_null;
684 status = dcerpc_auth_blob(rpc_out->data,
691 if (!NT_STATUS_IS_OK(status)) {
695 /* append the header */
696 if (!data_blob_append(NULL, rpc_out,
697 auth_info.data, auth_info.length)) {
698 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
699 (unsigned int)auth_info.length));
700 return NT_STATUS_NO_MEMORY;
702 data_blob_free(&auth_info);
704 switch (sec->auth_level) {
705 case DCERPC_AUTH_LEVEL_PRIVACY:
706 /* Data portion is encrypted. */
707 status = gensec_seal_packet(sec->gensec,
710 + DCERPC_RESPONSE_LENGTH,
715 if (!NT_STATUS_IS_OK(status)) {
720 case DCERPC_AUTH_LEVEL_INTEGRITY:
721 /* Data is signed. */
722 status = gensec_sign_packet(sec->gensec,
725 + DCERPC_RESPONSE_LENGTH,
730 if (!NT_STATUS_IS_OK(status)) {
737 smb_panic("bad auth level");
739 return NT_STATUS_INVALID_PARAMETER_MIX;
742 if (auth_blob.length != auth_len) {
743 return NT_STATUS_INVALID_PARAMETER_MIX;
746 /* Finally attach the blob. */
747 if (!data_blob_append(NULL, rpc_out,
748 auth_blob.data, auth_blob.length)) {
749 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
750 (unsigned int)auth_blob.length));
751 return NT_STATUS_NO_MEMORY;
753 data_blob_free(&auth_blob);
758 static NTSTATUS dcerpc_check_pdu_auth(struct dcerpc_security *sec,
759 struct ncacn_packet *pkt,
760 DATA_BLOB *pkt_trailer,
766 struct dcerpc_auth auth_info;
767 uint32_t auth_length;
771 switch (sec->auth_level) {
772 case DCERPC_AUTH_LEVEL_PRIVACY:
773 DEBUG(10, ("Requested Privacy.\n"));
776 case DCERPC_AUTH_LEVEL_INTEGRITY:
777 DEBUG(10, ("Requested Integrity.\n"));
780 case DCERPC_AUTH_LEVEL_CONNECT:
781 if (pkt->auth_length != 0) {
787 case DCERPC_AUTH_LEVEL_NONE:
788 if (pkt->auth_length != 0) {
789 DEBUG(3, ("Got non-zero auth len on non "
790 "authenticated connection!\n"));
791 return NT_STATUS_INVALID_PARAMETER;
797 DEBUG(3, ("Unimplemented Auth Level %d",
799 return NT_STATUS_INVALID_PARAMETER;
802 /* Paranioa checks for auth_length. */
803 if (pkt->auth_length > pkt->frag_length) {
804 return NT_STATUS_INFO_LENGTH_MISMATCH;
806 if (((unsigned int)pkt->auth_length
807 + DCERPC_AUTH_TRAILER_LENGTH < (unsigned int)pkt->auth_length) ||
808 ((unsigned int)pkt->auth_length
809 + DCERPC_AUTH_TRAILER_LENGTH < DCERPC_AUTH_TRAILER_LENGTH)) {
810 /* Integer wrap attempt. */
811 return NT_STATUS_INFO_LENGTH_MISMATCH;
814 status = dcerpc_pull_auth_trailer(pkt, pkt, pkt_trailer,
815 &auth_info, &auth_length, false);
816 if (!NT_STATUS_IS_OK(status)) {
820 if (auth_info.auth_type != sec->auth_type) {
821 return NT_STATUS_RPC_PROTOCOL_ERROR;
824 if (auth_info.auth_level != sec->auth_level) {
825 return NT_STATUS_RPC_PROTOCOL_ERROR;
828 if (auth_info.auth_context_id != sec->context_id) {
829 return NT_STATUS_RPC_PROTOCOL_ERROR;
832 data = data_blob_const(raw_pkt->data + header_size,
833 pkt_trailer->length - auth_length);
834 full_pkt = data_blob_const(raw_pkt->data,
835 raw_pkt->length - auth_info.credentials.length);
837 switch (sec->auth_type) {
838 case DCERPC_AUTH_TYPE_NONE:
839 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
845 switch (sec->auth_level) {
846 case DCERPC_AUTH_LEVEL_PRIVACY:
847 /* Data portion is encrypted. */
848 status = gensec_unseal_packet(sec->gensec,
853 &auth_info.credentials);
854 if (!NT_STATUS_IS_OK(status)) {
859 case DCERPC_AUTH_LEVEL_INTEGRITY:
860 /* Data is signed. */
861 status = gensec_check_packet(sec->gensec,
866 &auth_info.credentials);
867 if (!NT_STATUS_IS_OK(status)) {
872 return NT_STATUS_INVALID_PARAMETER;
874 /* TODO: remove later
875 * this is still needed because in the server code the
876 * pkt_trailer actually has a copy of the raw data, and they
877 * are still both used in later calls */
878 if (sec->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
879 memcpy(pkt_trailer->data, data.data, data.length);
882 *pad_len = auth_info.auth_pad_length;
883 data_blob_free(&auth_info.credentials);
887 static void dcerpc_connection_loop(struct tevent_req *subreq);
889 static NTSTATUS dcerpc_connection_loop_restart(struct dcerpc_connection *conn,
890 struct tevent_context *ev)
893 return NT_STATUS_INVALID_PARAMETER; // TODO...
896 if (conn->loop.subreq) {
897 if (conn->loop.ev != ev) {
898 return NT_STATUS_INVALID_PARAMETER; // TODO...
903 if (conn->calls.list == NULL) {
904 conn->loop.ev = NULL;
908 conn->loop.subreq = dcerpc_read_ncacn_packet_send(conn,
910 conn->transport.stream);
911 if (conn->loop.subreq == NULL) {
912 return NT_STATUS_NO_MEMORY;
914 tevent_req_set_callback(conn->loop.subreq, dcerpc_connection_loop, conn);
919 static void dcerpc_connection_loop(struct tevent_req *subreq)
921 struct dcerpc_connection *conn =
922 tevent_req_callback_data(subreq,
923 struct dcerpc_connection);
925 struct ncacn_packet *pkt;
927 struct dcerpc_call *call;
928 bool valid_type = false;
929 bool allow_fragments = false;
931 conn->loop.subreq = NULL;
933 error = dcerpc_read_ncacn_packet_recv(subreq, subreq, &pkt, &pdu);
934 if (!NT_STATUS_IS_OK(error)) {
936 dcerpc_connection_dead(conn, error);
940 if (DEBUGLEVEL >= 10) {
941 NDR_PRINT_DEBUG(ncacn_packet, pkt);
944 switch (pkt->ptype) {
945 case DCERPC_PKT_REQUEST:
946 /* Ordinary request. */
948 allow_fragments = true;
951 case DCERPC_PKT_PING:
952 /* Connectionless is server alive ? */
955 case DCERPC_PKT_RESPONSE:
956 /* Ordinary reply. */
958 allow_fragments = true;
961 case DCERPC_PKT_FAULT:
962 /* Fault in processing of call. */
966 case DCERPC_PKT_WORKING:
967 /* Connectionless reply to a ping when server busy. */
970 case DCERPC_PKT_NOCALL:
971 /* Connectionless reply to a ping when server has lost part of clients call. */
974 case DCERPC_PKT_REJECT:
975 /* Refuse a request with a code. */
981 case DCERPC_PKT_CL_CANCEL:
984 case DCERPC_PKT_FACK:
987 case DCERPC_PKT_CANCEL_ACK:
988 /* Server ACK to client cancel request. */
991 case DCERPC_PKT_BIND:
992 /* Bind to interface. */
996 case DCERPC_PKT_BIND_ACK:
997 /* Server ack of bind. */
1001 case DCERPC_PKT_BIND_NAK:
1002 /* Server nack of bind. */
1006 case DCERPC_PKT_ALTER:
1011 case DCERPC_PKT_ALTER_RESP:
1012 /* Reply to alter auth. */
1016 case DCERPC_PKT_AUTH3:
1017 /* not the real name! this is undocumented! */
1021 case DCERPC_PKT_SHUTDOWN:
1022 /* Server to client request to shutdown. */
1026 case DCERPC_PKT_CO_CANCEL:
1027 /* Connection-oriented cancel request. */
1031 case DCERPC_PKT_ORPHANED:
1032 /* Client telling server it's aborting a partially sent request or telling server to stop sending replies. */
1036 case DCERPC_PKT_RTS:
1037 /* RTS packets used in ncacn_http */
1042 TALLOC_FREE(subreq);
1043 dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1047 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1048 if (!allow_fragments) {
1049 TALLOC_FREE(subreq);
1050 dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1055 if (conn->calls.active != NULL) {
1057 if (pkt->call_id != conn->calls.active->call_id) {
1058 TALLOC_FREE(subreq);
1059 dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1063 if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) {
1064 TALLOC_FREE(subreq);
1065 dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1069 call = conn->calls.active;
1071 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1072 conn->calls.active = NULL;
1075 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
1076 TALLOC_FREE(subreq);
1077 dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1081 call = conn->calls.list;
1084 for (call = conn->calls.list; call; call = call->next) {
1085 if (call->call_id == pkt->call_id) {
1091 call = conn->calls.new_call;
1095 TALLOC_FREE(subreq);
1096 dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1100 if (call->incoming.handler == NULL) {
1101 TALLOC_FREE(subreq);
1102 dcerpc_connection_dead(conn, NT_STATUS_RPC_PROTOCOL_ERROR);
1106 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
1107 conn->calls.active = call;
1111 // reassemble and return
1114 error = call->incoming.handler(call->incoming.req, pkt, pdu);
1115 TALLOC_FREE(subreq);
1116 if (!NT_STATUS_IS_OK(error)) {
1117 dcerpc_connection_dead(conn, error);
1121 if (conn->calls.new_call == NULL) {
1122 conn->loop.ev = NULL;
1126 error = dcerpc_connection_loop_restart(conn, conn->loop.ev);
1127 if (!NT_STATUS_IS_OK(error)) {
1128 dcerpc_connection_dead(conn, error);
1133 struct dcerpc_do_bind_out_frag;
1135 struct dcerpc_do_bind_state {
1136 struct tevent_context *ev;
1137 struct dcerpc_connection *conn;
1138 struct dcerpc_call *call;
1139 struct dcerpc_security *sec;
1140 bool proposed_hdr_signing;
1142 NTSTATUS sec_status;
1144 struct dcerpc_do_bind_out_frag *out_frag;
1146 struct dcerpc_presentation **pres;
1147 uint32_t remaining_pres;
1150 struct dcerpc_ctx_list *ctx_list;
1151 struct ndr_syntax_id features;
1154 struct dcerpc_do_bind_out_frag {
1155 struct tevent_context *ev;
1156 struct dcerpc_connection *conn;
1157 struct tevent_req *req;
1158 enum dcerpc_pkt_type ptype;
1160 struct iovec vector;
1161 struct tevent_req *subreq_wait1;
1162 struct tevent_req *subreq_wait2;
1165 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
1166 enum tevent_req_state req_state);
1168 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq);
1169 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq);
1171 static NTSTATUS dcerpc_do_bind_handle_in_frag(struct tevent_req *req,
1172 struct ncacn_packet *pkt,
1175 struct tevent_req *dcerpc_do_bind_send(TALLOC_CTX *mem_ctx,
1176 struct tevent_context *ev,
1177 struct dcerpc_connection *conn,
1178 struct dcerpc_call *call,
1179 struct dcerpc_security *sec,
1181 struct dcerpc_presentation **pres)
1183 struct tevent_req *req;
1184 struct dcerpc_do_bind_state *state;
1185 struct tevent_req *subreq;
1187 req = tevent_req_create(mem_ctx, &state,
1188 struct dcerpc_do_bind_state);
1196 state->remaining_pres = num_pres;
1197 state->num_pres = num_pres;
1200 state->call->incoming.req = req;
1201 state->call->incoming.handler = dcerpc_do_bind_handle_in_frag;
1202 DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
1203 tevent_req_defer_callback(req, ev);
1204 tevent_req_set_cleanup_fn(req, dcerpc_do_bind_cleanup);
1206 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1207 subreq = gensec_update_send(state, ev,
1210 if (tevent_req_nomem(subreq, req)) {
1211 return tevent_req_post(req, ev);
1213 tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
1218 state->sec_status = NT_STATUS_OK;
1220 subreq = tevent_queue_wait_send(state, state->ev,
1221 state->conn->calls.out_queue);
1222 if (tevent_req_nomem(subreq, req)) {
1223 return tevent_req_post(req, ev);
1225 tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
1230 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
1231 enum tevent_req_state req_state)
1233 struct dcerpc_do_bind_state *state =
1234 tevent_req_data(req,
1235 struct dcerpc_do_bind_state);
1237 if (state->out_frag != NULL) {
1238 state->out_frag->req = NULL;
1239 state->out_frag = NULL;
1242 if (state->call != NULL) {
1243 if (state->call == state->conn->calls.active) {
1244 state->conn->calls.active = NULL;
1246 ZERO_STRUCT(state->call->incoming);
1247 DLIST_REMOVE(state->conn->calls.list, state->call);
1252 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq)
1254 struct tevent_req *req =
1255 tevent_req_callback_data(subreq,
1257 struct dcerpc_do_bind_state *state =
1258 tevent_req_data(req,
1259 struct dcerpc_do_bind_state);
1262 data_blob_free(&state->sec_out);
1263 status = gensec_update_recv(subreq, state, &state->sec_out);
1264 TALLOC_FREE(subreq);
1265 data_blob_free(&state->sec_in);
1266 state->sec_status = status;
1267 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1268 status = NT_STATUS_OK;
1270 if (!NT_STATUS_IS_OK(status)) {
1271 tevent_req_nterror(req, status);
1275 if (NT_STATUS_IS_OK(state->sec_status) &&
1276 state->sec_out.length == 0)
1278 tevent_req_done(req);
1282 if (state->sec->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1283 state->sec->client_hdr_signing =
1284 gensec_have_feature(state->sec->gensec,
1285 GENSEC_FEATURE_SIGN_PKT_HEADER);
1288 subreq = tevent_queue_wait_send(state, state->ev,
1289 state->conn->calls.out_queue);
1290 if (tevent_req_nomem(subreq, req)) {
1293 tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
1296 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq);
1297 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq);
1298 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq);
1300 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq)
1302 struct tevent_req *req =
1303 tevent_req_callback_data(subreq,
1305 struct dcerpc_do_bind_state *state =
1306 tevent_req_data(req,
1307 struct dcerpc_do_bind_state);
1308 struct dcerpc_do_bind_out_frag *frag;
1309 size_t auth_len = 0;
1311 DATA_BLOB auth_info = data_blob_null;
1312 uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1313 union dcerpc_payload u;
1315 bool require_ack = false;
1316 bool use_trans = true;
1319 ok = tevent_queue_wait_recv(subreq);
1321 //status = NT_STATUS_INTERNAL_ERROR;
1322 tevent_req_oom(req);
1325 TALLOC_FREE(subreq);
1328 * the fragment belongs to the connection instead of the request
1329 * because it has to remain in case the request is canceled
1331 frag = talloc_zero(state->conn, struct dcerpc_do_bind_out_frag);
1332 if (tevent_req_nomem(frag, req)) {
1335 frag->ev = state->ev;
1336 frag->conn = state->conn;
1338 state->out_frag = frag;
1340 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1341 if (state->sec->client_hdr_signing &&
1342 !state->proposed_hdr_signing)
1344 state->proposed_hdr_signing = true;
1345 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1350 //TODO : DCERPC_PFC_FLAG_CONC_MPX
1352 //TODO: remaining_pres
1354 if (!state->conn->features.bind_done) {
1355 frag->ptype = DCERPC_PKT_BIND;
1356 } else if (require_ack) {
1357 frag->ptype = DCERPC_PKT_ALTER;
1358 } else if (state->remaining_pres > 0) {
1359 frag->ptype = DCERPC_PKT_ALTER;
1360 } else if (!NT_STATUS_IS_OK(state->sec_status)) {
1361 frag->ptype = DCERPC_PKT_ALTER;
1363 frag->ptype = DCERPC_PKT_AUTH3;
1366 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1367 status = dcerpc_auth_blob(frag,
1368 state->sec->auth_type,
1369 state->sec->auth_level,
1370 0, /* auth_pad_length */
1371 state->sec->context_id, /* auth_context_id */
1374 if (!NT_STATUS_IS_OK(status)) {
1375 tevent_req_nterror(req, status);
1379 auth_len = auth_info.length;
1382 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1386 state->num_ctx = state->num_pres;
1387 if (!state->conn->assoc->negotiate_done) {
1388 state->num_ctx += 1;
1391 state->ctx_list = talloc_zero_array(frag,
1392 struct dcerpc_ctx_list,
1394 if (tevent_req_nomem(state->ctx_list, req)) {
1398 for (i=0; i < state->num_pres; i++) {
1399 state->ctx_list[i] = state->pres[i]->negotiate.req;
1402 if (!state->conn->assoc->negotiate_done) {
1403 state->features = dcerpc_construct_bind_time_features(
1404 state->conn->assoc->client_features);
1406 state->ctx_list[i].context_id = state->conn->next_pres_context_id;
1408 state->ctx_list[i].abstract_syntax =
1409 state->ctx_list[i-1].abstract_syntax;
1411 state->ctx_list[i].num_transfer_syntaxes = 1;
1412 state->ctx_list[i].transfer_syntaxes = &state->features;
1415 switch (frag->ptype) {
1416 case DCERPC_PKT_BIND:
1417 case DCERPC_PKT_ALTER:
1418 u.bind.max_xmit_frag = state->conn->features.max_xmit_frag;
1419 u.bind.max_recv_frag = state->conn->features.max_recv_frag;
1420 u.bind.assoc_group_id = state->conn->assoc->assoc_group_id;
1421 u.bind.num_contexts = state->num_ctx;
1422 u.bind.ctx_list = state->ctx_list;
1423 u.bind.auth_info = auth_info;
1426 case DCERPC_PKT_AUTH3:
1428 u.auth3.auth_info = auth_info;
1431 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1435 status = dcerpc_ncacn_packet_blob(frag,
1439 state->call->call_id,
1442 if (!NT_STATUS_IS_OK(status)) {
1443 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1444 tevent_req_nterror(req, status);
1448 if (frag->ptype == DCERPC_PKT_AUTH3) {
1452 if (frag->conn->transport.use_trans_fn == NULL) {
1456 if (frag->conn->loop.subreq != NULL) {
1460 if (frag->conn->features.concurrent_multiplex) {
1464 if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
1469 frag->subreq_wait1 = tevent_queue_wait_send(frag,
1471 frag->conn->transport.write_queue);
1472 if (tevent_req_nomem(req, frag->subreq_wait1)) {
1475 tevent_req_set_callback(frag->subreq_wait1,
1476 dcerpc_do_bind_out_frag_trans_wait1,
1479 * we need to block reads until our write is
1480 * the next in the write queue.
1482 frag->conn->loop.subreq = frag->subreq_wait1;
1483 frag->conn->loop.ev = frag->ev;
1487 * We need to add a dcerpc_write_fragment_queue_send/recv()
1490 frag->vector.iov_base = frag->blob.data;
1491 frag->vector.iov_len = frag->blob.length;
1492 subreq = tstream_writev_queue_send(frag, frag->ev,
1493 frag->conn->transport.stream,
1494 frag->conn->transport.write_queue,
1496 if (tevent_req_nomem(subreq, req)) {
1499 tevent_req_set_callback(subreq,
1500 dcerpc_do_bind_out_frag_done,
1504 frag->subreq_wait2 = tevent_queue_wait_send(frag,
1506 frag->conn->transport.write_queue);
1507 if (tevent_req_nomem(req, frag->subreq_wait2)) {
1510 tevent_req_set_callback(frag->subreq_wait2,
1511 dcerpc_do_bind_out_frag_trans_wait2,
1515 if (frag->ptype == DCERPC_PKT_AUTH3) {
1519 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1520 if (tevent_req_nterror(req, status)) {
1525 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq)
1527 struct dcerpc_do_bind_out_frag *frag =
1528 tevent_req_callback_data(subreq,
1529 struct dcerpc_do_bind_out_frag);
1530 struct dcerpc_connection *conn = frag->conn;
1536 * TODO; what if the caller has been free'ed?
1537 * TALLOC_FREE(frag->subreq_write)
1540 frag->subreq_wait1 = NULL;
1541 conn->loop.subreq = NULL;
1543 ok = tevent_queue_wait_recv(subreq);
1546 dcerpc_connection_dead(conn, NT_STATUS_INTERNAL_ERROR);
1550 if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
1552 * We added 3 entries into the queue,
1553 * wait1, writev and wait2.
1555 * There's more to write, we should not block
1556 * further writev calls for a trans call.
1558 * The wait2 stage will trigger the read.
1560 TALLOC_FREE(subreq);
1565 * we don't need wait2 anymore, we're sure that
1566 * we'll do a trans call.
1568 TALLOC_FREE(frag->subreq_wait2);
1570 status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
1571 if (!NT_STATUS_IS_OK(status)) {
1573 dcerpc_connection_dead(conn, status);
1577 /* we free subreq after tstream_cli_np_use_trans */
1578 TALLOC_FREE(subreq);
1580 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1581 if (!NT_STATUS_IS_OK(status)) {
1583 dcerpc_connection_dead(conn, status);
1588 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq)
1590 struct dcerpc_do_bind_out_frag *frag =
1591 tevent_req_callback_data(subreq,
1592 struct dcerpc_do_bind_out_frag);
1593 struct dcerpc_connection *conn = frag->conn;
1594 struct tevent_req *req = frag->req;
1600 * If the caller has been free'ed, we have should
1601 * ignore any errors and just free 'frag'
1604 struct dcerpc_do_bind_state *state =
1605 tevent_req_data(req,
1606 struct dcerpc_do_bind_state);
1608 state->out_frag = NULL;
1611 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1612 TALLOC_FREE(subreq);
1615 status = map_nt_error_from_unix_common(sys_errno);
1616 dcerpc_connection_dead(conn, status);
1620 if (frag->ptype == DCERPC_PKT_AUTH3) {
1625 tevent_req_done(req);
1629 if (frag->subreq_wait2 != NULL) {
1635 /* we need to wait for incoming pdus */
1638 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq)
1640 struct dcerpc_do_bind_out_frag *frag =
1641 tevent_req_callback_data(subreq,
1642 struct dcerpc_do_bind_out_frag);
1643 struct dcerpc_connection *conn = frag->conn;
1647 frag->subreq_wait2 = NULL;
1649 ok = tevent_queue_wait_recv(subreq);
1652 dcerpc_connection_dead(conn, NT_STATUS_INTERNAL_ERROR);
1656 TALLOC_FREE(subreq);
1658 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1659 if (!NT_STATUS_IS_OK(status)) {
1661 dcerpc_connection_dead(conn, status);
1667 /* we need to wait for incoming pdus */
1670 static NTSTATUS dcerpc_do_bind_handle_in_frag(struct tevent_req *req,
1671 struct ncacn_packet *pkt,
1674 struct dcerpc_do_bind_state *state =
1675 tevent_req_data(req,
1676 struct dcerpc_do_bind_state);
1678 struct dcerpc_presentation *last_pres = NULL;
1679 size_t num_pres_ok = 0;
1682 /* Ensure we have the correct type. */
1683 switch (pkt->ptype) {
1684 case DCERPC_PKT_BIND_ACK:
1685 case DCERPC_PKT_ALTER_RESP:
1686 if (!state->conn->features.bind_done) {
1687 if (pkt->u.bind_ack.max_recv_frag < 1234) {
1688 return NT_STATUS_RPC_PROTOCOL_ERROR;
1690 if (pkt->u.bind_ack.max_xmit_frag < 1234) {
1691 return NT_STATUS_RPC_PROTOCOL_ERROR;
1693 state->conn->features.max_recv_frag =
1694 pkt->u.bind_ack.max_recv_frag;
1695 state->conn->features.max_xmit_frag =
1696 pkt->u.bind_ack.max_xmit_frag;
1698 if (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) {
1699 state->conn->features.concurrent_multiplex = true;
1702 state->conn->features.bind_done = true;
1705 if (!state->conn->assoc->negotiate_done) {
1706 state->conn->assoc->negotiate_done = true;
1707 state->conn->assoc->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
1710 if (pkt->u.bind_ack.assoc_group_id != state->conn->assoc->assoc_group_id) {
1711 return NT_STATUS_RPC_PROTOCOL_ERROR;
1714 if (pkt->u.bind_ack.num_results > state->num_ctx) {
1715 return NT_STATUS_RPC_PROTOCOL_ERROR;
1718 state->remaining_pres = 0;
1720 if (state->proposed_hdr_signing) {
1721 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1722 state->sec->hdr_signing = true;
1726 for (i = 0; i < pkt->u.bind_ack.num_results; i++) {
1727 struct dcerpc_ack_ctx *ack = &pkt->u.bind_ack.ctx_list[i];
1729 if (i < state->num_pres) {
1730 struct dcerpc_ack_ctx *pack =
1731 &state->pres[i]->negotiate.ack;
1733 if (ack->result == DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1734 return NT_STATUS_RPC_PROTOCOL_ERROR;
1737 if (ack->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1743 if (pack->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1745 * if a presentation context was valid it must
1746 * be valid for the lifetime of the connection
1748 return NT_STATUS_RPC_PROTOCOL_ERROR;
1752 last_pres = state->pres[i];
1756 if (ack->result != DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1760 state->conn->assoc->features = state->conn->assoc->client_features;
1761 state->conn->assoc->features &= ack->reason.negotiate;
1764 for (i = 0; i < state->num_pres; i++) {
1765 struct dcerpc_ack_ctx *ack = &state->pres[i]->negotiate.ack;
1768 if (ack->result != DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1772 ok = ndr_syntax_id_equal(&state->pres[i]->transfer,
1775 return NT_STATUS_RPC_PROTOCOL_ERROR;
1779 if (num_pres_ok == 0 && last_pres != NULL) {
1780 status = dcerpc_presentation_status(last_pres);
1781 tevent_req_nterror(req, status);
1782 return NT_STATUS_OK;
1785 if (pkt->auth_length >= 8) {
1786 struct tevent_req *subreq;
1788 state->sec_in = data_blob_talloc(state,
1789 pkt->u.bind_ack.auth_info.data + 8,
1790 pkt->u.bind_ack.auth_info.length - 8);
1792 subreq = gensec_update_send(state, state->ev,
1795 if (tevent_req_nomem(subreq, req)) {
1796 return NT_STATUS_OK;
1798 tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
1799 return NT_STATUS_OK;
1802 tevent_req_done(req);
1803 return NT_STATUS_OK;
1805 //case DCERPC_PKT_ALTER_RESP:
1806 if (pkt->auth_length != 0) {
1807 return NT_STATUS_NOT_IMPLEMENTED;
1810 return NT_STATUS_NOT_IMPLEMENTED;
1813 /* Point the return values at the NDR data. */
1814 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
1816 if (pkt->auth_length) {
1817 /* We've already done integer wrap tests in
1818 * dcerpc_check_auth(). */
1819 payload.length = frag.length
1820 - DCERPC_RESPONSE_LENGTH
1822 - DCERPC_AUTH_TRAILER_LENGTH
1825 payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
1828 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1829 if (pkt->drep[0] & DCERPC_DREP_LE) {
1830 state->response.bigendian = false;
1832 state->response.bigendian = true;
1836 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
1837 (long unsigned int)frag.length,
1838 (long unsigned int)payload.length,
1839 (unsigned int)pad_len));
1842 * If this is the first reply, and the allocation hint is
1843 * reasonable, try and set up the reply_pdu DATA_BLOB to the
1847 if ((state->response.blob.length == 0) &&
1848 pkt->u.response.alloc_hint &&
1849 (pkt->u.response.alloc_hint < 15*1024*1024)) {
1850 ok = data_blob_realloc(state, &state->response.blob,
1851 pkt->u.response.alloc_hint);
1853 DEBUG(0, ("reply alloc hint %d too "
1854 "large to allocate\n",
1855 (int)pkt->u.response.alloc_hint));
1856 return NT_STATUS_NO_MEMORY;
1860 new_total = state->response.ofs + payload.length;
1862 if (new_total > 15 * 1024 *1024) {
1863 return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
1866 missing = new_total - state->response.blob.length;
1869 ok = data_blob_realloc(state, &state->response.blob,
1872 DEBUG(0, ("reply alloc hint %d too "
1873 "large to allocate\n",
1874 (int)pkt->u.response.alloc_hint));
1875 return NT_STATUS_NO_MEMORY;
1879 memcpy(state->response.blob.data + state->response.ofs,
1880 payload.data, payload.length);
1881 state->response.ofs += payload.length;
1883 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1884 tevent_req_done(req);//TODO
1885 return NT_STATUS_OK;
1887 return NT_STATUS_OK;
1889 return NT_STATUS_NOT_IMPLEMENTED;
1891 case DCERPC_PKT_FAULT:
1893 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1894 "code %s received from %s!\n",
1895 dcerpc_errstr(talloc_tos(),
1896 pkt->u.fault.status),
1899 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
1900 if (NT_STATUS_IS_OK(status)) {
1901 status = NT_STATUS_RPC_PROTOCOL_ERROR;
1904 tevent_req_nterror(req, status);//TODO
1905 return NT_STATUS_OK;
1907 DEBUG(0, ("Unknown packet type %u received from %s!\n",
1908 (unsigned int)pkt->ptype,
1910 return NT_STATUS_RPC_PROTOCOL_ERROR;
1913 return NT_STATUS_RPC_PROTOCOL_ERROR;
1916 NTSTATUS dcerpc_do_bind_recv(struct tevent_req *req)
1918 struct dcerpc_do_bind_state *state =
1919 tevent_req_data(req,
1920 struct dcerpc_do_bind_state);
1923 if (tevent_req_is_nterror(req, &status)) {
1924 tevent_req_received(req);
1928 if (!NT_STATUS_IS_OK(state->sec_status)) {
1929 status = state->sec_status;
1930 tevent_req_received(req);
1934 tevent_req_received(req);
1935 return NT_STATUS_OK;
1938 struct dcerpc_do_request_out_frag;
1940 struct dcerpc_do_request_state {
1941 struct tevent_context *ev;
1942 struct dcerpc_connection *conn;
1943 struct dcerpc_call *call;
1944 const struct GUID *object;
1947 const DATA_BLOB *blob;
1953 bool verify_bitmask1;
1954 bool verify_pcontext;
1956 struct dcerpc_do_request_out_frag *out_frag;
1964 struct dcerpc_do_request_out_frag {
1965 struct tevent_context *ev;
1966 struct dcerpc_connection *conn;
1967 struct tevent_req *req;
1970 struct iovec vector;
1971 struct tevent_req *subreq_wait1;
1972 struct tevent_req *subreq_wait2;
1975 static void dcerpc_do_request_cleanup(struct tevent_req *req,
1976 enum tevent_req_state req_state);
1978 static void dcerpc_do_request_verification_trailer(struct tevent_req *req);
1979 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
1980 void *private_data);
1982 static NTSTATUS dcerpc_do_request_handle_in_frag(struct tevent_req *req,
1983 struct ncacn_packet *pkt,
1986 struct tevent_req *dcerpc_do_request_send(TALLOC_CTX *mem_ctx,
1987 struct tevent_context *ev,
1988 struct dcerpc_connection *conn,
1989 struct dcerpc_call *call,
1990 const struct GUID *object,
1992 const DATA_BLOB *request,
1995 struct tevent_req *req;
1996 struct dcerpc_do_request_state *state;
1999 req = tevent_req_create(mem_ctx, &state,
2000 struct dcerpc_do_request_state);
2007 state->object = object;
2008 state->opnum = opnum;
2009 state->request.blob = request;
2010 state->request.bigendian = bigendian;
2012 dcerpc_do_request_verification_trailer(req);
2013 if (!tevent_req_is_in_progress(req)) {
2014 return tevent_req_post(req, ev);
2017 state->call->incoming.req = req;
2018 state->call->incoming.handler = dcerpc_do_request_handle_in_frag;
2019 DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
2020 tevent_req_defer_callback(req, ev);
2021 tevent_req_set_cleanup_fn(req, dcerpc_do_request_cleanup);
2023 ok = tevent_queue_add(state->conn->calls.out_queue,
2026 dcerpc_do_request_out_frag_next,
2029 tevent_req_nomem(NULL, req);
2030 return tevent_req_post(req, ev);
2036 static void dcerpc_do_request_cleanup(struct tevent_req *req,
2037 enum tevent_req_state req_state)
2039 struct dcerpc_do_request_state *state =
2040 tevent_req_data(req,
2041 struct dcerpc_do_request_state);
2043 if (state->out_frag != NULL) {
2044 state->out_frag->req = NULL;
2045 state->out_frag = NULL;
2048 if (state->call != NULL) {
2049 if (state->call == state->conn->calls.active) {
2050 state->conn->calls.active = NULL;
2052 ZERO_STRUCT(state->call->incoming);
2053 DLIST_REMOVE(state->conn->calls.list, state->call);
2058 static void dcerpc_do_request_verification_trailer(struct tevent_req *req)
2060 struct dcerpc_do_request_state *state =
2061 tevent_req_data(req,
2062 struct dcerpc_do_request_state);
2063 struct dcerpc_sec_verification_trailer *t;
2064 struct dcerpc_sec_vt *c = NULL;
2065 struct ndr_push *ndr = NULL;
2066 enum ndr_err_code ndr_err;
2070 if (state->call->sec->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
2074 t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
2075 if (tevent_req_nomem(t, req)) {
2079 if (!state->call->sec->verified_bitmask1) {
2080 t->commands = talloc_realloc(t, t->commands,
2081 struct dcerpc_sec_vt,
2082 t->count.count + 1);
2083 if (tevent_req_nomem(t->commands, req)) {
2086 c = &t->commands[t->count.count++];
2089 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
2090 if (state->call->sec->client_hdr_signing) {
2091 c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
2093 state->verify_bitmask1 = true;
2096 if (!state->call->pres->verified_pcontext) {
2097 t->commands = talloc_realloc(t, t->commands,
2098 struct dcerpc_sec_vt,
2099 t->count.count + 1);
2100 if (tevent_req_nomem(t->commands, req)) {
2103 c = &t->commands[t->count.count++];
2106 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
2107 c->u.pcontext.abstract_syntax = state->call->pres->table->syntax_id;
2108 c->u.pcontext.transfer_syntax = state->call->pres->transfer;
2110 state->verify_pcontext = true;
2113 if (!state->call->sec->hdr_signing) {
2114 t->commands = talloc_realloc(t, t->commands,
2115 struct dcerpc_sec_vt,
2116 t->count.count + 1);
2117 if (tevent_req_nomem(t->commands, req)) {
2120 c = &t->commands[t->count.count++];
2123 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
2124 c->u.header2.ptype = DCERPC_PKT_REQUEST;
2125 if (state->request.bigendian) {
2126 c->u.header2.drep[0] = 0;
2128 c->u.header2.drep[0] = DCERPC_DREP_LE;
2130 c->u.header2.drep[1] = 0;
2131 c->u.header2.drep[2] = 0;
2132 c->u.header2.drep[3] = 0;
2133 c->u.header2.call_id = state->call->call_id;
2134 c->u.header2.context_id = 0;
2135 c->u.header2.opnum = state->opnum;
2138 if (t->count.count == 0) {
2143 c = &t->commands[t->count.count - 1];
2144 c->command |= DCERPC_SEC_VT_COMMAND_END;
2146 if (DEBUGLEVEL >= 10) {
2147 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
2150 ndr = ndr_push_init_ctx(state);
2151 if (tevent_req_nomem(ndr, req)) {
2155 //TODO if (state->request.bigendian)
2157 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
2158 NDR_SCALARS | NDR_BUFFERS,
2160 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2161 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
2162 tevent_req_nterror(req, status);
2165 state->request.trailer = ndr_push_blob(ndr);
2167 align = state->request.blob->length & 0x3;
2174 const uint8_t zeros[4] = { 0, };
2176 ok = data_blob_append(ndr, &state->request.trailer, zeros, pad);
2178 tevent_req_oom(req);
2182 /* move the padding to the start */
2183 p = state->request.trailer.data;
2184 memmove(p + pad, p, state->request.trailer.length - pad);
2191 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq);
2192 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq);
2193 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq);
2195 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
2198 struct dcerpc_do_request_state *state =
2199 tevent_req_data(req,
2200 struct dcerpc_do_request_state);
2201 struct dcerpc_do_request_out_frag *frag;
2202 size_t hdr_len = DCERPC_REQUEST_LENGTH;
2208 size_t data_thistime;
2209 size_t trailer_left;
2210 size_t trailer_thistime = 0;
2212 size_t total_thistime;
2214 union dcerpc_payload u;
2216 struct tevent_req *subreq;
2217 bool use_trans = true;
2219 if (state->object) {
2220 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
2225 * the fragment belongs to the connection instead of the request
2226 * because it has to remain in case the request is canceled
2228 frag = talloc_zero(state->conn, struct dcerpc_do_request_out_frag);
2229 if (tevent_req_nomem(frag, req)) {
2232 frag->ev = state->ev;
2233 frag->conn = state->conn;
2235 state->out_frag = frag;
2237 data_left = state->request.blob->length - state->request.ofs;
2238 trailer_left = state->request.trailer.length - state->request.trailer_ofs;
2239 total_left = data_left + trailer_left;
2240 if (total_left < data_left || total_left < trailer_left) {
2241 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2245 status = dcerpc_guess_pdu_sizes(state->call->sec,
2246 hdr_len, total_left,
2247 state->conn->features.max_xmit_frag,
2248 DCERPC_PAYLOAD_PADDING_SIZE,
2250 &frag_len, &auth_len, &pad_len);
2251 if (!NT_STATUS_IS_OK(status)) {
2252 tevent_req_nterror(req, status);
2256 if (state->request.ofs == 0) {
2257 flags |= DCERPC_PFC_FLAG_FIRST;
2260 if (total_thistime == total_left) {
2261 flags |= DCERPC_PFC_FLAG_LAST;
2264 data_thistime = MIN(total_thistime, data_left);
2265 if (data_thistime < total_thistime) {
2266 trailer_thistime = total_thistime - data_thistime;
2269 ZERO_STRUCT(u.request);
2271 u.request.alloc_hint = total_left;
2272 u.request.context_id = state->call->pres->context_id;
2273 u.request.opnum = state->opnum;
2274 if (state->object) {
2275 u.request.object.object = *state->object;
2277 //TODO pass state->request.bigendian
2278 status = dcerpc_ncacn_packet_blob(frag,
2282 state->call->call_id,
2285 if (!NT_STATUS_IS_OK(status)) {
2286 tevent_req_nterror(req, status);
2290 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2291 * compute it right for requests because the auth trailer is missing
2293 dcerpc_set_frag_length(&frag->blob, frag_len);
2295 if (data_thistime > 0) {
2296 const uint8_t *data_ptr;
2298 data_ptr = state->request.blob->data;
2299 data_ptr += state->request.ofs;
2301 /* Copy in the data. */
2302 ok = data_blob_append(frag, &frag->blob,
2303 data_ptr, data_thistime);
2305 tevent_req_oom(req);
2309 state->request.ofs += data_thistime;
2312 if (trailer_thistime > 0) {
2313 const uint8_t *trailer_ptr;
2315 trailer_ptr = state->request.trailer.data;
2316 trailer_ptr += state->request.trailer_ofs;
2318 /* Copy in the data. */
2319 ok = data_blob_append(frag, &frag->blob,
2320 trailer_ptr, trailer_thistime);
2322 tevent_req_oom(req);
2326 state->request.trailer_ofs += trailer_thistime;
2329 switch (state->call->sec->auth_level) {
2330 case DCERPC_AUTH_LEVEL_NONE:
2331 case DCERPC_AUTH_LEVEL_CONNECT:
2332 case DCERPC_AUTH_LEVEL_PACKET:
2334 case DCERPC_AUTH_LEVEL_INTEGRITY:
2335 case DCERPC_AUTH_LEVEL_PRIVACY:
2336 status = dcerpc_response_auth_blob(state->call->sec,
2340 if (!NT_STATUS_IS_OK(status)) {
2341 tevent_req_nterror(req, status);
2346 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2350 frag->is_last = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2352 if (!frag->is_last) {
2356 if (frag->conn->transport.use_trans_fn == NULL) {
2360 if (frag->conn->loop.subreq != NULL) {
2364 if (frag->conn->features.concurrent_multiplex) {
2368 if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
2373 frag->subreq_wait1 = tevent_queue_wait_send(frag,
2375 frag->conn->transport.write_queue);
2376 if (tevent_req_nomem(req, frag->subreq_wait1)) {
2379 tevent_req_set_callback(frag->subreq_wait1,
2380 dcerpc_do_request_out_frag_trans_wait1,
2383 * we need to block reads until our write is
2384 * the next in the write queue.
2386 frag->conn->loop.subreq = frag->subreq_wait1;
2387 frag->conn->loop.ev = frag->ev;
2391 * We need to add a dcerpc_write_fragment_queue_send/recv()
2394 frag->vector.iov_base = frag->blob.data;
2395 frag->vector.iov_len = frag->blob.length;
2396 subreq = tstream_writev_queue_send(frag, frag->ev,
2397 frag->conn->transport.stream,
2398 frag->conn->transport.write_queue,
2400 if (tevent_req_nomem(subreq, req)) {
2403 tevent_req_set_callback(subreq,
2404 dcerpc_do_request_out_frag_done,
2408 frag->subreq_wait2 = tevent_queue_wait_send(frag,
2410 frag->conn->transport.write_queue);
2411 if (tevent_req_nomem(req, frag->subreq_wait2)) {
2414 tevent_req_set_callback(frag->subreq_wait2,
2415 dcerpc_do_request_out_frag_trans_wait2,
2419 if (!frag->is_last) {
2423 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2424 if (tevent_req_nterror(req, status)) {
2429 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq)
2431 struct dcerpc_do_request_out_frag *frag =
2432 tevent_req_callback_data(subreq,
2433 struct dcerpc_do_request_out_frag);
2434 struct tevent_req *req = frag->req;
2439 * TODO; what if the caller has been free'ed?
2442 frag->subreq_wait1 = NULL;
2443 frag->conn->loop.subreq = NULL;
2445 ok = tevent_queue_wait_recv(subreq);
2447 status = NT_STATUS_INTERNAL_ERROR;
2450 tevent_req_nterror(req, status);
2452 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2456 if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
2458 * We added 3 entries into the queue,
2459 * wait1, writev and wait2.
2461 * There's more to write, we should not block
2462 * further writev calls for a trans call.
2464 * The wait2 stage will trigger the read.
2466 TALLOC_FREE(subreq);
2471 * we don't need wait2 anymore, we're sure that
2472 * we'll do a trans call.
2474 TALLOC_FREE(frag->subreq_wait2);
2476 status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
2477 if (!NT_STATUS_IS_OK(status)) {
2480 tevent_req_nterror(req, status);
2482 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2486 /* we free subreq after tstream_cli_np_use_trans */
2487 TALLOC_FREE(subreq);
2489 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2490 if (!NT_STATUS_IS_OK(status)) {
2493 tevent_req_nterror(req, status);
2495 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2500 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq)
2502 struct dcerpc_do_request_out_frag *frag =
2503 tevent_req_callback_data(subreq,
2504 struct dcerpc_do_request_out_frag);
2505 struct tevent_req *req = frag->req;
2511 * If the caller has been free'ed, we have should
2512 * ignore any errors and just free 'frag'
2515 struct dcerpc_do_request_state *state =
2516 tevent_req_data(req,
2517 struct dcerpc_do_request_state);
2519 state->out_frag = NULL;
2522 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2523 TALLOC_FREE(subreq);
2526 status = map_nt_error_from_unix_common(sys_errno);
2528 tevent_req_nterror(req, status);
2533 if (frag->subreq_wait2 != NULL) {
2537 if (frag->is_last) {
2547 dcerpc_do_request_out_frag_next(req, NULL);
2550 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq)
2552 struct dcerpc_do_request_out_frag *frag =
2553 tevent_req_callback_data(subreq,
2554 struct dcerpc_do_request_out_frag);
2555 struct tevent_req *req = frag->req;
2559 frag->subreq_wait2 = NULL;
2561 ok = tevent_queue_wait_recv(subreq);
2563 status = NT_STATUS_INTERNAL_ERROR;
2566 tevent_req_nterror(req, status);
2568 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2572 TALLOC_FREE(subreq);
2574 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2575 if (!NT_STATUS_IS_OK(status)) {
2578 tevent_req_nterror(req, status);
2580 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2586 /* we need to wait for incoming pdus */
2589 static NTSTATUS dcerpc_do_request_handle_in_frag(struct tevent_req *req,
2590 struct ncacn_packet *pkt,
2593 struct dcerpc_do_request_state *state =
2594 tevent_req_data(req,
2595 struct dcerpc_do_request_state);
2604 /* Ensure we have the correct type. */
2605 switch (pkt->ptype) {
2606 case DCERPC_PKT_RESPONSE:
2608 /* Here's where we deal with incoming sign/seal. */
2609 error = dcerpc_check_pdu_auth(state->call->sec,
2611 &pkt->u.response.stub_and_verifier,
2612 DCERPC_RESPONSE_LENGTH,
2614 if (!NT_STATUS_IS_OK(error)) {
2618 if (!state->got_first) {
2619 state->got_first = true;
2621 if (pkt->drep[0] & DCERPC_DREP_LE) {
2622 state->response.bigendian = false;
2624 state->response.bigendian = true;
2627 if (state->verify_bitmask1) {
2628 state->call->sec->verified_bitmask1 = true;
2631 if (state->verify_pcontext) {
2632 state->call->pres->verified_pcontext = true;
2636 if (state->response.bigendian) {
2637 if (pkt->drep[0] != 0) {
2638 return NT_STATUS_RPC_PROTOCOL_ERROR;
2641 if (pkt->drep[0] != DCERPC_DREP_LE) {
2642 return NT_STATUS_RPC_PROTOCOL_ERROR;
2645 if (pkt->drep[1] != 0) {
2646 return NT_STATUS_RPC_PROTOCOL_ERROR;
2648 if (pkt->drep[2] != 0) {
2649 return NT_STATUS_RPC_PROTOCOL_ERROR;
2651 if (pkt->drep[3] != 0) {
2652 return NT_STATUS_RPC_PROTOCOL_ERROR;
2655 if (pkt->u.response.context_id != state->call->pres->context_id) {
2656 return NT_STATUS_RPC_PROTOCOL_ERROR;
2659 if (frag.length < DCERPC_RESPONSE_LENGTH + pad_len) {
2660 return NT_STATUS_RPC_PROTOCOL_ERROR;
2663 /* Point the return values at the NDR data. */
2664 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
2666 if (pkt->auth_length) {
2667 /* We've already done integer wrap tests in
2668 * dcerpc_check_auth(). */
2669 payload.length = frag.length
2670 - DCERPC_RESPONSE_LENGTH
2672 - DCERPC_AUTH_TRAILER_LENGTH
2675 payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
2678 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
2679 (long unsigned int)frag.length,
2680 (long unsigned int)payload.length,
2681 (unsigned int)pad_len));
2684 * If this is the first reply, and the allocation hint is
2685 * reasonable, try and set up the reply_pdu DATA_BLOB to the
2689 if ((state->response.blob.length == 0) &&
2690 pkt->u.response.alloc_hint &&
2691 (pkt->u.response.alloc_hint < 15*1024*1024)) {
2692 ok = data_blob_realloc(state, &state->response.blob,
2693 pkt->u.response.alloc_hint);
2695 DEBUG(0, ("reply alloc hint %d too "
2696 "large to allocate\n",
2697 (int)pkt->u.response.alloc_hint));
2698 return NT_STATUS_NO_MEMORY;
2702 new_total = state->response.ofs + payload.length;
2704 if (new_total > 15 * 1024 *1024) {
2705 return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
2708 missing = new_total - state->response.blob.length;
2711 ok = data_blob_realloc(state, &state->response.blob,
2714 DEBUG(0, ("reply alloc hint %d too "
2715 "large to allocate\n",
2716 (int)pkt->u.response.alloc_hint));
2717 return NT_STATUS_NO_MEMORY;
2721 memcpy(state->response.blob.data + state->response.ofs,
2722 payload.data, payload.length);
2723 state->response.ofs += payload.length;
2725 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
2726 tevent_req_done(req);//TODO
2727 return NT_STATUS_OK;
2730 return dcerpc_connection_loop_restart(state->conn, state->ev);
2732 case DCERPC_PKT_FAULT:
2734 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
2735 "code %s received from %s!\n",
2736 dcerpc_errstr(talloc_tos(),
2737 pkt->u.fault.status),
2740 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
2741 if (NT_STATUS_IS_OK(status)) {
2742 status = NT_STATUS_RPC_PROTOCOL_ERROR;
2745 tevent_req_nterror(req, status);//TODO
2746 return NT_STATUS_OK;
2748 DEBUG(0, ("Unknown packet type %u received from %s!\n",
2749 (unsigned int)pkt->ptype,
2751 return NT_STATUS_RPC_PROTOCOL_ERROR;
2755 NTSTATUS dcerpc_do_request_recv(struct tevent_req *req,
2756 TALLOC_CTX *mem_ctx,
2757 DATA_BLOB *response,
2760 struct dcerpc_do_request_state *state =
2761 tevent_req_data(req,
2762 struct dcerpc_do_request_state);
2765 if (tevent_req_is_nterror(req, &status)) {
2766 tevent_req_received(req);
2770 /* return data to caller and assign it ownership of memory */
2771 response->data = talloc_move(mem_ctx, &state->response.blob.data);
2772 response->length = state->response.blob.length;
2773 *bigendian = state->response.bigendian;
2775 tevent_req_received(req);
2776 return NT_STATUS_OK;
2779 struct dcerpc_server_connection_loop_state {
2780 struct tevent_context *ev;
2781 struct dcerpc_connection *conn;
2783 struct dcerpc_server *server;
2785 struct dcerpc_server_association *assoc;
2787 uint32_t last_call_id;
2790 struct db_context *secs;
2793 struct db_context *pres;
2796 static void dcerpc_server_connection_loop_cleanup(struct tevent_req *req,
2797 enum tevent_req_state req_state);
2799 static NTSTATUS dcerpc_server_connection_loop_handle_in_frag(struct tevent_req *req,
2800 struct ncacn_packet *pkt,
2803 struct tevent_req *dcerpc_server_connection_loop_send(TALLOC_CTX *mem_ctx,
2804 struct tevent_context *ev,
2805 struct dcerpc_connection *conn,
2806 struct dcerpc_server *server)
2808 struct tevent_req *req;
2809 struct dcerpc_server_connection_loop_state *state;
2810 struct dcerpc_call *call;
2812 req = tevent_req_create(mem_ctx, &state,
2813 struct dcerpc_server_connection_loop_state);
2820 if (state->conn->calls.new_call != NULL) {
2821 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2822 return tevent_req_post(req, ev);
2825 call = talloc_zero(state, struct dcerpc_call);
2830 call->incoming.req = req;
2831 call->incoming.handler = dcerpc_server_connection_loop_handle_in_frag;
2832 conn->calls.new_call = call;
2833 tevent_req_defer_callback(req, ev);
2834 tevent_req_set_cleanup_fn(req, dcerpc_server_connection_loop_cleanup);
2836 //TODO different dcerpc_connection_dead() behavior as server?
2841 static void dcerpc_server_connection_loop_cleanup(struct tevent_req *req,
2842 enum tevent_req_state req_state)
2844 struct dcerpc_server_connection_loop_state *state =
2845 tevent_req_data(req,
2846 struct dcerpc_server_connection_loop_state);
2848 if (state->conn != NULL) {
2849 TALLOC_FREE(state->conn->calls.new_call);
2854 static NTSTATUS dcerpc_server_connection_loop_handle_in_frag(struct tevent_req *req,
2855 struct ncacn_packet *pkt,
2858 struct dcerpc_server_connection_loop_state *state =
2859 tevent_req_data(req,
2860 struct dcerpc_server_connection_loop_state);
2862 /* Ensure we have the correct type. */
2863 switch (pkt->ptype) {
2864 case DCERPC_PKT_BIND:
2865 if (state->conn->features.bind_done) {
2866 return NT_STATUS_RPC_PROTOCOL_ERROR;
2868 state->conn->features.bind_done = true;
2871 case DCERPC_PKT_ALTER:
2872 if (!state->conn->features.bind_done) {
2873 return NT_STATUS_RPC_PROTOCOL_ERROR;
2877 case DCERPC_PKT_REQUEST:
2878 if (!state->conn->features.bind_done) {
2879 return NT_STATUS_RPC_PROTOCOL_ERROR;
2884 DEBUG(0, ("Unknown packet type %u received from %s!\n",
2885 (unsigned int)pkt->ptype,
2887 return NT_STATUS_RPC_PROTOCOL_ERROR;
2890 return NT_STATUS_NOT_IMPLEMENTED;
2893 NTSTATUS dcerpc_server_connection_loop_recv(struct tevent_req *req)
2895 return tevent_req_simple_recv_ntstatus(req);