2 * Unix SMB/CIFS implementation.
3 * DCERPC client routines
5 * Copyright (C) Stefan Metzmacher 2011
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "system/network.h"
24 #include "lib/util/tevent_ntstatus.h"
25 #include "lib/tsocket/tsocket.h"
26 #include "librpc/gen_ndr/ndr_dcerpc.h"
27 #include "source3/librpc/rpc/dcerpc.h"
28 #include "source4/librpc/rpc/dcerpc.h"
29 #include "auth/gensec/gensec.h"
30 #include "librpc/rpc/dcerpc_connection.h"
31 #include "../lib/util/dlinklist.h"
33 struct dcerpc_association;
34 struct dcerpc_connection;
35 struct dcerpc_security;
36 struct dcerpc_presentation;
39 struct dcerpc_association {
40 uint32_t assoc_group_id;
41 uint16_t client_features;
44 uint32_t next_call_id;
47 struct dcerpc_connection {
48 struct dcerpc_association *assoc;
51 struct tstream_context *stream;
52 dcerpc_connection_use_trans_fn use_trans_fn;
53 struct tevent_queue *write_queue;
57 uint16_t max_xmit_frag;
58 uint16_t max_recv_frag;
59 bool concurrent_multiplex;
63 uint32_t next_sec_context_id;
64 uint16_t next_pres_context_id;
67 struct tevent_queue *out_queue;
68 struct dcerpc_call *list;
69 struct dcerpc_call *active;
70 struct dcerpc_call *new_call;
74 struct tevent_context *ev;
75 struct tevent_req *subreq;
79 struct dcerpc_security {
81 enum dcerpc_AuthType auth_type;
82 enum dcerpc_AuthLevel auth_level;
83 struct gensec_security *gensec;
84 bool client_hdr_signing;
86 bool verified_bitmask1;
89 struct dcerpc_presentation {
91 const struct ndr_interface_table *table;
92 struct ndr_syntax_id transfer;
94 struct dcerpc_ctx_list req;
95 struct dcerpc_ack_ctx ack;
97 bool verified_pcontext;
101 struct dcerpc_call *prev, *next;
104 struct dcerpc_security *sec;
105 struct dcerpc_presentation *pres;
109 NTSTATUS (*handler)(void *private_data,
110 struct ncacn_packet *pkt,
115 struct dcerpc_association *dcerpc_association_create(TALLOC_CTX *mem_ctx,
116 uint16_t client_features)
118 struct dcerpc_association *assoc;
120 assoc = talloc_zero(mem_ctx, struct dcerpc_association);
125 assoc->next_call_id = 1;
127 assoc->client_features = client_features;
132 struct dcerpc_connection *dcerpc_connection_create(TALLOC_CTX *mem_ctx,
133 struct dcerpc_association *assoc,
134 struct tstream_context **stream)
136 struct dcerpc_connection *conn;
138 conn = talloc_zero(mem_ctx, struct dcerpc_connection);
144 conn->transport.stream = talloc_move(conn, stream);
145 conn->transport.write_queue = tevent_queue_create(conn, "write_queue");
146 if (conn->transport.write_queue == NULL) {
151 conn->features.max_xmit_frag = 4280;
152 conn->features.max_recv_frag = 4280;
154 conn->calls.out_queue = tevent_queue_create(conn, "out_queue");
155 if (conn->calls.out_queue == NULL) {
163 void dcerpc_connection_set_use_trans_fn(struct dcerpc_connection *conn,
164 dcerpc_connection_use_trans_fn fn)
166 conn->transport.use_trans_fn = fn;
169 struct dcerpc_security *dcerpc_security_allocate(
171 struct dcerpc_connection *conn,
172 enum dcerpc_AuthType auth_type,
173 enum dcerpc_AuthLevel auth_level,
174 struct gensec_security **gensec)
176 struct dcerpc_security *sec;
178 sec = talloc_zero(mem_ctx, struct dcerpc_security);
183 sec->context_id = conn->next_sec_context_id++;
184 sec->auth_type = auth_type;
185 sec->auth_level = auth_level;
187 if (gensec != NULL) {
188 sec->gensec = talloc_move(sec, gensec);
194 struct dcerpc_presentation *dcerpc_presentation_allocate(
196 struct dcerpc_connection *conn,
197 const struct ndr_interface_table *table,
198 const struct ndr_syntax_id *transfer)
200 struct dcerpc_presentation *pres;
202 pres = talloc_zero(mem_ctx, struct dcerpc_presentation);
207 pres->context_id = conn->next_pres_context_id++;
209 pres->transfer = *transfer;
211 pres->negotiate.req.abstract_syntax = table->syntax_id;
212 pres->negotiate.req.context_id = pres->context_id;
213 pres->negotiate.req.num_transfer_syntaxes = 1;
214 pres->negotiate.req.transfer_syntaxes = &pres->transfer;
216 pres->negotiate.ack.result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
217 pres->negotiate.ack.reason.value =
218 DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
223 struct dcerpc_call *dcerpc_call_allocate(TALLOC_CTX *mem_ctx,
224 struct dcerpc_association *assoc,
225 struct dcerpc_security *sec,
226 struct dcerpc_presentation *pres)
228 struct dcerpc_call *call;
230 call = talloc_zero(mem_ctx, struct dcerpc_call);
235 call->call_id = assoc->next_call_id++;
243 static NTSTATUS dcerpc_guess_pdu_sizes(struct dcerpc_security *sec,
246 size_t max_xmit_frag,
247 size_t pad_alignment,
248 size_t *data_to_send,
256 /* no auth token cases first */
257 switch (sec->auth_level) {
258 case DCERPC_AUTH_LEVEL_NONE:
259 case DCERPC_AUTH_LEVEL_CONNECT:
260 case DCERPC_AUTH_LEVEL_PACKET:
261 max_len = max_xmit_frag - header_len;
262 *data_to_send = MIN(max_len, data_left);
265 *frag_len = header_len + *data_to_send;
268 case DCERPC_AUTH_LEVEL_PRIVACY:
269 case DCERPC_AUTH_LEVEL_INTEGRITY:
270 if (sec->auth_type == DCERPC_AUTH_TYPE_NONE) {
271 return NT_STATUS_INVALID_PARAMETER_MIX;
273 if (sec->gensec == NULL) {
274 return NT_STATUS_INVALID_PARAMETER_MIX;
279 return NT_STATUS_INVALID_PARAMETER;
283 /* Sign/seal case, calculate auth and pad lengths */
285 max_len = max_xmit_frag - header_len - DCERPC_AUTH_TRAILER_LENGTH;
287 *auth_len = gensec_sig_size(sec->gensec, max_len);
289 max_len -= *auth_len;
291 *data_to_send = MIN(max_len, data_left);
293 mod_len = (header_len + *data_to_send) % pad_alignment;
295 *pad_len = pad_alignment - mod_len;
300 if (*data_to_send + *pad_len > max_len) {
301 *data_to_send -= pad_alignment;
304 *frag_len = header_len + *data_to_send + *pad_len
305 + DCERPC_AUTH_TRAILER_LENGTH + *auth_len;
310 static NTSTATUS dcerpc_ncacn_push_auth(DATA_BLOB *blob,
312 struct ncacn_packet *pkt,
313 struct dcerpc_auth *auth_info)
315 struct ndr_push *ndr;
316 enum ndr_err_code ndr_err;
318 ndr = ndr_push_init_ctx(mem_ctx);
320 return NT_STATUS_NO_MEMORY;
323 if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
324 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
327 if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
328 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
332 pkt->auth_length = auth_info->credentials.length;
334 // pkt->auth_length = 0;
337 ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
338 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
339 return ndr_map_error2ntstatus(ndr_err);
344 /* the s3 rpc server doesn't handle auth padding in
345 bind requests. Use zero auth padding to keep us
346 working with old servers */
347 uint32_t offset = ndr->offset;
348 ndr_err = ndr_push_align(ndr, 16);
349 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
350 return ndr_map_error2ntstatus(ndr_err);
352 auth_info->auth_pad_length = ndr->offset - offset;
354 auth_info->auth_pad_length = 0;
356 ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, auth_info);
357 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
358 return ndr_map_error2ntstatus(ndr_err);
362 *blob = ndr_push_blob(ndr);
364 /* fill in the frag length */
365 dcerpc_set_frag_length(blob, blob->length);
370 static NTSTATUS dcerpc_ncacn_packet_blob(TALLOC_CTX *mem_ctx,
371 enum dcerpc_pkt_type ptype,
373 uint16_t auth_length,
375 union dcerpc_payload *u,
378 struct ncacn_packet r;
382 r.rpc_vers_minor = 0;
384 r.pfc_flags = pfc_flags;
385 r.drep[0] = DCERPC_DREP_LE;
389 r.auth_length = auth_length;
393 status = dcerpc_ncacn_push_auth(blob, mem_ctx, &r, NULL);
394 if (!NT_STATUS_IS_OK(status)) {
398 if (DEBUGLEVEL >= 10) {
399 /* set frag len for print function */
400 r.frag_length = blob->length;
401 NDR_PRINT_DEBUG(ncacn_packet, &r);
407 #define DCERPC_PAYLOAD_PADDING_SIZE 16 //TODO???
409 static NTSTATUS dcerpc_auth_blob(TALLOC_CTX *mem_ctx,
410 enum dcerpc_AuthType auth_type,
411 enum dcerpc_AuthLevel auth_level,
412 uint8_t auth_pad_length,
413 uint32_t auth_context_id,
414 const DATA_BLOB *credentials,
417 struct dcerpc_auth r;
418 enum ndr_err_code ndr_err;
420 r.auth_type = auth_type;
421 r.auth_level = auth_level;
422 r.auth_pad_length = auth_pad_length;
424 r.auth_context_id = auth_context_id;
425 r.credentials = *credentials;
427 ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r,
428 (ndr_push_flags_fn_t)ndr_push_dcerpc_auth);
429 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
430 return ndr_map_error2ntstatus(ndr_err);
433 if (DEBUGLEVEL >= 10) {
434 NDR_PRINT_DEBUG(dcerpc_auth, &r);
440 static NTSTATUS dcerpc_response_auth_blob(struct dcerpc_security *sec,
444 char pad[DCERPC_PAYLOAD_PADDING_SIZE] = { 0, };
447 uint16_t data_and_pad_len = 0;
450 if (rpc_out->length < DCERPC_RESPONSE_LENGTH) {
451 return NT_STATUS_INVALID_PARAMETER_MIX;
454 if (sec->auth_type == DCERPC_AUTH_TYPE_NONE ||
455 sec->auth_type == DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM) {
459 if (sec->gensec == NULL) {
460 return NT_STATUS_INVALID_PARAMETER_MIX;
464 /* Copy the sign/seal padding data. */
465 if (!data_blob_append(NULL, rpc_out, pad, pad_len)) {
466 return NT_STATUS_NO_MEMORY;
470 data_and_pad_len = rpc_out->length - DCERPC_RESPONSE_LENGTH;
472 /* marshall the dcerpc_auth with an actually empty auth_blob.
473 * This is needed because the ntmlssp signature includes the
474 * auth header. We will append the actual blob later. */
475 auth_blob = data_blob_null;
476 status = dcerpc_auth_blob(rpc_out->data,
483 if (!NT_STATUS_IS_OK(status)) {
487 /* append the header */
488 if (!data_blob_append(NULL, rpc_out,
489 auth_info.data, auth_info.length)) {
490 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
491 (unsigned int)auth_info.length));
492 return NT_STATUS_NO_MEMORY;
494 data_blob_free(&auth_info);
496 switch (sec->auth_level) {
497 case DCERPC_AUTH_LEVEL_PRIVACY:
498 /* Data portion is encrypted. */
499 status = gensec_seal_packet(sec->gensec,
502 + DCERPC_RESPONSE_LENGTH,
507 if (!NT_STATUS_IS_OK(status)) {
512 case DCERPC_AUTH_LEVEL_INTEGRITY:
513 /* Data is signed. */
514 status = gensec_sign_packet(sec->gensec,
517 + DCERPC_RESPONSE_LENGTH,
522 if (!NT_STATUS_IS_OK(status)) {
529 smb_panic("bad auth level");
531 return NT_STATUS_INVALID_PARAMETER;
534 /* Finally attach the blob. */
535 if (!data_blob_append(NULL, rpc_out,
536 auth_blob.data, auth_blob.length)) {
537 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
538 (unsigned int)auth_blob.length));
539 return NT_STATUS_NO_MEMORY;
541 data_blob_free(&auth_blob);
546 static NTSTATUS dcerpc_check_pdu_auth(struct dcerpc_security *sec,
547 struct ncacn_packet *pkt,
548 DATA_BLOB *pkt_trailer,
554 struct dcerpc_auth auth_info;
555 uint32_t auth_length;
559 switch (sec->auth_level) {
560 case DCERPC_AUTH_LEVEL_PRIVACY:
561 DEBUG(10, ("Requested Privacy.\n"));
564 case DCERPC_AUTH_LEVEL_INTEGRITY:
565 DEBUG(10, ("Requested Integrity.\n"));
568 case DCERPC_AUTH_LEVEL_CONNECT:
569 if (pkt->auth_length != 0) {
575 case DCERPC_AUTH_LEVEL_NONE:
576 if (pkt->auth_length != 0) {
577 DEBUG(3, ("Got non-zero auth len on non "
578 "authenticated connection!\n"));
579 return NT_STATUS_INVALID_PARAMETER;
585 DEBUG(3, ("Unimplemented Auth Level %d",
587 return NT_STATUS_INVALID_PARAMETER;
590 /* Paranioa checks for auth_length. */
591 if (pkt->auth_length > pkt->frag_length) {
592 return NT_STATUS_INFO_LENGTH_MISMATCH;
594 if (((unsigned int)pkt->auth_length
595 + DCERPC_AUTH_TRAILER_LENGTH < (unsigned int)pkt->auth_length) ||
596 ((unsigned int)pkt->auth_length
597 + DCERPC_AUTH_TRAILER_LENGTH < DCERPC_AUTH_TRAILER_LENGTH)) {
598 /* Integer wrap attempt. */
599 return NT_STATUS_INFO_LENGTH_MISMATCH;
602 status = dcerpc_pull_auth_trailer(pkt, pkt, pkt_trailer,
603 &auth_info, &auth_length, false);
604 if (!NT_STATUS_IS_OK(status)) {
608 if (auth_info.auth_type != sec->auth_type) {
609 return NT_STATUS_RPC_PROTOCOL_ERROR;
612 if (auth_info.auth_level != sec->auth_level) {
613 return NT_STATUS_RPC_PROTOCOL_ERROR;
616 if (auth_info.auth_context_id != sec->context_id) {
617 return NT_STATUS_RPC_PROTOCOL_ERROR;
620 data = data_blob_const(raw_pkt->data + header_size,
621 pkt_trailer->length - auth_length);
622 full_pkt = data_blob_const(raw_pkt->data,
623 raw_pkt->length - auth_info.credentials.length);
625 switch (sec->auth_type) {
626 case DCERPC_AUTH_TYPE_NONE:
627 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
633 switch (sec->auth_level) {
634 case DCERPC_AUTH_LEVEL_PRIVACY:
635 /* Data portion is encrypted. */
636 status = gensec_unseal_packet(sec->gensec,
641 &auth_info.credentials);
642 if (!NT_STATUS_IS_OK(status)) {
647 case DCERPC_AUTH_LEVEL_INTEGRITY:
648 /* Data is signed. */
649 status = gensec_check_packet(sec->gensec,
654 &auth_info.credentials);
655 if (!NT_STATUS_IS_OK(status)) {
660 return NT_STATUS_INVALID_PARAMETER;
662 /* TODO: remove later
663 * this is still needed because in the server code the
664 * pkt_trailer actually has a copy of the raw data, and they
665 * are still both used in later calls */
666 if (sec->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
667 memcpy(pkt_trailer->data, data.data, data.length);
670 *pad_len = auth_info.auth_pad_length;
671 data_blob_free(&auth_info.credentials);
675 static void dcerpc_connection_loop(struct tevent_req *subreq);
677 static NTSTATUS dcerpc_connection_loop_restart(struct dcerpc_connection *conn,
678 struct tevent_context *ev)
681 return NT_STATUS_INVALID_PARAMETER; // TODO...
684 if (conn->loop.subreq) {
685 if (conn->loop.ev != ev) {
686 return NT_STATUS_INVALID_PARAMETER; // TODO...
691 if (conn->calls.list == NULL) {
692 conn->loop.ev = NULL;
696 conn->loop.subreq = dcerpc_read_ncacn_packet_send(conn,
698 conn->transport.stream);
699 if (conn->loop.subreq == NULL) {
700 return NT_STATUS_NO_MEMORY;
702 tevent_req_set_callback(conn->loop.subreq, dcerpc_connection_loop, conn);
707 static void dcerpc_connection_loop(struct tevent_req *subreq)
709 struct dcerpc_connection *conn =
710 tevent_req_callback_data(subreq,
711 struct dcerpc_connection);
713 struct ncacn_packet *pkt;
715 struct dcerpc_call *call;
716 bool valid_type = false;
717 bool allow_fragments = false;
719 conn->loop.subreq = NULL;
721 error = dcerpc_read_ncacn_packet_recv(subreq, subreq, &pkt, &pdu);
722 if (!NT_STATUS_IS_OK(error)) {
724 // disconnect and notify pending calls
728 if (DEBUGLEVEL >= 10) {
729 NDR_PRINT_DEBUG(ncacn_packet, pkt);
732 switch (pkt->ptype) {
733 case DCERPC_PKT_REQUEST:
734 /* Ordinary request. */
736 allow_fragments = true;
739 case DCERPC_PKT_PING:
740 /* Connectionless is server alive ? */
743 case DCERPC_PKT_RESPONSE:
744 /* Ordinary reply. */
746 allow_fragments = true;
749 case DCERPC_PKT_FAULT:
750 /* Fault in processing of call. */
754 case DCERPC_PKT_WORKING:
755 /* Connectionless reply to a ping when server busy. */
758 case DCERPC_PKT_NOCALL:
759 /* Connectionless reply to a ping when server has lost part of clients call. */
762 case DCERPC_PKT_REJECT:
763 /* Refuse a request with a code. */
769 case DCERPC_PKT_CL_CANCEL:
772 case DCERPC_PKT_FACK:
775 case DCERPC_PKT_CANCEL_ACK:
776 /* Server ACK to client cancel request. */
779 case DCERPC_PKT_BIND:
780 /* Bind to interface. */
784 case DCERPC_PKT_BIND_ACK:
785 /* Server ack of bind. */
789 case DCERPC_PKT_BIND_NAK:
790 /* Server nack of bind. */
794 case DCERPC_PKT_ALTER:
799 case DCERPC_PKT_ALTER_RESP:
800 /* Reply to alter auth. */
804 case DCERPC_PKT_AUTH3:
805 /* not the real name! this is undocumented! */
809 case DCERPC_PKT_SHUTDOWN:
810 /* Server to client request to shutdown. */
814 case DCERPC_PKT_CO_CANCEL:
815 /* Connection-oriented cancel request. */
819 case DCERPC_PKT_ORPHANED:
820 /* Client telling server it's aborting a partially sent request or telling server to stop sending replies. */
825 /* RTS packets used in ncacn_http */
831 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
835 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
836 if (!allow_fragments) {
838 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
843 if (conn->calls.active != NULL) {
845 if (pkt->call_id != conn->calls.active->call_id) {
847 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
851 if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) {
853 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
857 call = conn->calls.active;
859 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
860 conn->calls.active = NULL;
863 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
865 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
869 call = conn->calls.list;
872 for (call = conn->calls.list; call; call = call->next) {
873 if (call->call_id == pkt->call_id) {
879 call = conn->calls.new_call;
884 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
888 if (call->incoming.handler == NULL) {
890 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
894 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
895 conn->calls.active = call;
899 // reassemble and return
902 error = call->incoming.handler(call->incoming.private_data, pkt, pdu);
904 if (!NT_STATUS_IS_OK(error)) {
905 // disconnect and notify pending calls
909 if (conn->calls.new_call == NULL) {
910 conn->loop.ev = NULL;
914 error = dcerpc_connection_loop_restart(conn, conn->loop.ev);
915 if (!NT_STATUS_IS_OK(error)) {
916 // disconnect and notify pending calls
921 struct dcerpc_do_bind_out_frag;
923 struct dcerpc_do_bind_state {
924 struct tevent_context *ev;
925 struct dcerpc_connection *conn;
926 struct dcerpc_call *call;
927 struct dcerpc_security *sec;
928 bool proposed_hdr_signing;
932 struct dcerpc_do_bind_out_frag *out_frag;
934 struct dcerpc_presentation **pres;
935 uint32_t remaining_pres;
938 struct dcerpc_ctx_list *ctx_list;
939 struct ndr_syntax_id features;
942 struct dcerpc_do_bind_out_frag {
943 struct tevent_context *ev;
944 struct dcerpc_connection *conn;
945 struct tevent_req *req;
946 enum dcerpc_pkt_type ptype;
949 struct tevent_req *subreq_wait1;
950 struct tevent_req *subreq_wait2;
953 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
954 enum tevent_req_state req_state);
956 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq);
957 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq);
959 static NTSTATUS dcerpc_do_bind_handle_in_frag(void *private_data,
960 struct ncacn_packet *pkt,
963 struct tevent_req *dcerpc_do_bind_send(TALLOC_CTX *mem_ctx,
964 struct tevent_context *ev,
965 struct dcerpc_connection *conn,
966 struct dcerpc_call *call,
967 struct dcerpc_security *sec,
969 struct dcerpc_presentation **pres)
971 struct tevent_req *req;
972 struct dcerpc_do_bind_state *state;
973 struct tevent_req *subreq;
975 req = tevent_req_create(mem_ctx, &state,
976 struct dcerpc_do_bind_state);
984 state->remaining_pres = num_pres;
985 state->num_pres = num_pres;
988 state->call->incoming.private_data = req;
989 state->call->incoming.handler = dcerpc_do_bind_handle_in_frag;
990 DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
992 tevent_req_set_cleanup_fn(req, dcerpc_do_bind_cleanup);
993 tevent_req_defer_callback(req, ev);
995 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
996 subreq = gensec_update_send(state, ev,
999 if (tevent_req_nomem(subreq, req)) {
1000 return tevent_req_post(req, ev);
1002 tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
1007 state->sec_status = NT_STATUS_OK;
1009 subreq = tevent_queue_wait_send(state, state->ev,
1010 state->conn->calls.out_queue);
1011 if (tevent_req_nomem(subreq, req)) {
1012 return tevent_req_post(req, ev);
1014 tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
1019 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
1020 enum tevent_req_state req_state)
1022 struct dcerpc_do_bind_state *state =
1023 tevent_req_data(req,
1024 struct dcerpc_do_bind_state);
1026 if (state->out_frag != NULL) {
1027 state->out_frag->req = NULL;
1028 state->out_frag = NULL;
1031 if (state->call != NULL) {
1032 ZERO_STRUCT(state->call->incoming);
1033 DLIST_REMOVE(state->conn->calls.list, state->call);
1038 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq)
1040 struct tevent_req *req =
1041 tevent_req_callback_data(subreq,
1043 struct dcerpc_do_bind_state *state =
1044 tevent_req_data(req,
1045 struct dcerpc_do_bind_state);
1048 data_blob_free(&state->sec_out);
1049 status = gensec_update_recv(subreq, state, &state->sec_out);
1050 TALLOC_FREE(subreq);
1051 data_blob_free(&state->sec_in);
1052 state->sec_status = status;
1053 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1054 status = NT_STATUS_OK;
1056 if (!NT_STATUS_IS_OK(status)) {
1057 tevent_req_nterror(req, status);
1061 if (NT_STATUS_IS_OK(state->sec_status) &&
1062 state->sec_out.length == 0)
1064 tevent_req_done(req);
1068 if (state->sec->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1069 state->sec->client_hdr_signing =
1070 gensec_have_feature(state->sec->gensec,
1071 GENSEC_FEATURE_SIGN_PKT_HEADER);
1074 subreq = tevent_queue_wait_send(state, state->ev,
1075 state->conn->calls.out_queue);
1076 if (tevent_req_nomem(subreq, req)) {
1079 tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
1082 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq);
1083 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq);
1084 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq);
1086 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq)
1088 struct tevent_req *req =
1089 tevent_req_callback_data(subreq,
1091 struct dcerpc_do_bind_state *state =
1092 tevent_req_data(req,
1093 struct dcerpc_do_bind_state);
1094 struct dcerpc_do_bind_out_frag *frag;
1095 size_t auth_len = 0;
1097 DATA_BLOB auth_info = data_blob_null;
1098 uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1099 union dcerpc_payload u;
1101 bool require_ack = false;
1102 bool use_trans = true;
1105 ok = tevent_queue_wait_recv(subreq);
1107 //status = NT_STATUS_INTERNAL_ERROR;
1108 tevent_req_oom(req);
1111 TALLOC_FREE(subreq);
1114 * the fragment belongs to the connection instead of the request
1115 * because it has to remain in case the request is canceled
1117 frag = talloc_zero(state->conn, struct dcerpc_do_bind_out_frag);
1118 if (tevent_req_nomem(frag, req)) {
1121 frag->ev = state->ev;
1122 frag->conn = state->conn;
1124 state->out_frag = frag;
1126 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1127 if (state->sec->client_hdr_signing &&
1128 !state->proposed_hdr_signing)
1130 state->proposed_hdr_signing = true;
1131 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1136 //TODO : DCERPC_PFC_FLAG_CONC_MPX
1138 //TODO: remaining_pres
1140 if (!state->conn->features.bind_done) {
1141 frag->ptype = DCERPC_PKT_BIND;
1142 } else if (require_ack) {
1143 frag->ptype = DCERPC_PKT_ALTER;
1144 } else if (state->remaining_pres > 0) {
1145 frag->ptype = DCERPC_PKT_ALTER;
1146 } else if (!NT_STATUS_IS_OK(state->sec_status)) {
1147 frag->ptype = DCERPC_PKT_ALTER;
1149 frag->ptype = DCERPC_PKT_AUTH3;
1152 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1153 status = dcerpc_auth_blob(frag,
1154 state->sec->auth_type,
1155 state->sec->auth_level,
1156 0, /* auth_pad_length */
1157 state->sec->context_id, /* auth_context_id */
1160 if (!NT_STATUS_IS_OK(status)) {
1161 tevent_req_nterror(req, status);
1165 auth_len = auth_info.length;
1168 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1172 state->num_ctx = state->num_pres;
1173 if (!state->conn->assoc->negotiate_done) {
1174 state->num_ctx += 1;
1177 state->ctx_list = talloc_zero_array(frag,
1178 struct dcerpc_ctx_list,
1180 if (tevent_req_nomem(state->ctx_list, req)) {
1184 for (i=0; i < state->num_pres; i++) {
1185 state->ctx_list[i] = state->pres[i]->negotiate.req;
1188 if (!state->conn->assoc->negotiate_done) {
1189 state->features = dcerpc_construct_bind_time_features(
1190 state->conn->assoc->client_features);
1192 state->ctx_list[i].context_id = state->conn->next_pres_context_id;
1194 state->ctx_list[i].abstract_syntax =
1195 state->ctx_list[i-1].abstract_syntax;
1197 state->ctx_list[i].num_transfer_syntaxes = 1;
1198 state->ctx_list[i].transfer_syntaxes = &state->features;
1201 switch (frag->ptype) {
1202 case DCERPC_PKT_BIND:
1203 case DCERPC_PKT_ALTER:
1204 u.bind.max_xmit_frag = state->conn->features.max_xmit_frag;
1205 u.bind.max_recv_frag = state->conn->features.max_recv_frag;
1206 u.bind.assoc_group_id = state->conn->assoc->assoc_group_id;
1207 u.bind.num_contexts = state->num_ctx;
1208 u.bind.ctx_list = state->ctx_list;
1209 u.bind.auth_info = auth_info;
1212 case DCERPC_PKT_AUTH3:
1214 u.auth3.auth_info = auth_info;
1217 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1221 status = dcerpc_ncacn_packet_blob(frag,
1225 state->call->call_id,
1228 if (!NT_STATUS_IS_OK(status)) {
1229 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1230 tevent_req_nterror(req, status);
1234 if (frag->ptype == DCERPC_PKT_AUTH3) {
1238 if (frag->conn->transport.use_trans_fn == NULL) {
1242 if (frag->conn->loop.subreq != NULL) {
1246 if (frag->conn->features.concurrent_multiplex) {
1250 if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
1255 frag->subreq_wait1 = tevent_queue_wait_send(frag,
1257 frag->conn->transport.write_queue);
1258 if (tevent_req_nomem(req, frag->subreq_wait1)) {
1261 tevent_req_set_callback(frag->subreq_wait1,
1262 dcerpc_do_bind_out_frag_trans_wait1,
1265 * we need to block reads until our write is
1266 * the next in the write queue.
1268 frag->conn->loop.subreq = frag->subreq_wait1;
1269 frag->conn->loop.ev = frag->ev;
1273 * We need to add a dcerpc_write_fragment_queue_send/recv()
1276 frag->vector.iov_base = frag->blob.data;
1277 frag->vector.iov_len = frag->blob.length;
1278 subreq = tstream_writev_queue_send(frag, frag->ev,
1279 frag->conn->transport.stream,
1280 frag->conn->transport.write_queue,
1282 if (tevent_req_nomem(subreq, req)) {
1285 tevent_req_set_callback(subreq,
1286 dcerpc_do_bind_out_frag_done,
1290 frag->subreq_wait2 = tevent_queue_wait_send(frag,
1292 frag->conn->transport.write_queue);
1293 if (tevent_req_nomem(req, frag->subreq_wait2)) {
1296 tevent_req_set_callback(frag->subreq_wait2,
1297 dcerpc_do_bind_out_frag_trans_wait2,
1301 if (frag->ptype == DCERPC_PKT_AUTH3) {
1305 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1306 if (tevent_req_nterror(req, status)) {
1311 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq)
1313 struct dcerpc_do_bind_out_frag *frag =
1314 tevent_req_callback_data(subreq,
1315 struct dcerpc_do_bind_out_frag);
1316 struct tevent_req *req = frag->req;
1321 * TODO; what if the caller has been free'ed?
1324 frag->subreq_wait1 = NULL;
1325 frag->conn->loop.subreq = NULL;
1327 ok = tevent_queue_wait_recv(subreq);
1329 status = NT_STATUS_INTERNAL_ERROR;
1332 tevent_req_nterror(req, status);
1334 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1338 if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
1340 * We added 3 entries into the queue,
1341 * wait1, writev and wait2.
1343 * There's more to write, we should not block
1344 * further writev calls for a trans call.
1346 * The wait2 stage will trigger the read.
1348 TALLOC_FREE(subreq);
1353 * we don't need wait2 anymore, we're sure that
1354 * we'll do a trans call.
1356 TALLOC_FREE(frag->subreq_wait2);
1358 status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
1359 if (!NT_STATUS_IS_OK(status)) {
1362 tevent_req_nterror(req, status);
1364 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1368 /* we free subreq after tstream_cli_np_use_trans */
1369 TALLOC_FREE(subreq);
1371 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1372 if (!NT_STATUS_IS_OK(status)) {
1375 tevent_req_nterror(req, status);
1377 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1382 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq)
1384 struct dcerpc_do_bind_out_frag *frag =
1385 tevent_req_callback_data(subreq,
1386 struct dcerpc_do_bind_out_frag);
1387 struct tevent_req *req = frag->req;
1393 * If the caller has been free'ed, we have should
1394 * ignore any errors and just free 'frag'
1397 struct dcerpc_do_bind_state *state =
1398 tevent_req_data(req,
1399 struct dcerpc_do_bind_state);
1401 state->out_frag = NULL;
1404 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1405 TALLOC_FREE(subreq);
1408 status = map_nt_error_from_unix_common(sys_errno);
1410 tevent_req_nterror(req, status);
1415 if (frag->ptype == DCERPC_PKT_AUTH3) {
1420 tevent_req_done(req);
1424 if (frag->subreq_wait2 != NULL) {
1430 /* we need to wait for incoming pdus */
1433 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq)
1435 struct dcerpc_do_bind_out_frag *frag =
1436 tevent_req_callback_data(subreq,
1437 struct dcerpc_do_bind_out_frag);
1438 struct tevent_req *req = frag->req;
1442 frag->subreq_wait2 = NULL;
1444 ok = tevent_queue_wait_recv(subreq);
1446 status = NT_STATUS_INTERNAL_ERROR;
1449 tevent_req_nterror(req, status);
1451 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1455 TALLOC_FREE(subreq);
1457 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1458 if (!NT_STATUS_IS_OK(status)) {
1461 tevent_req_nterror(req, status);
1463 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1469 /* we need to wait for incoming pdus */
1472 static NTSTATUS dcerpc_do_bind_handle_in_frag(void *private_data,
1473 struct ncacn_packet *pkt,
1476 struct tevent_req *req =
1477 talloc_get_type_abort(private_data,
1479 struct dcerpc_do_bind_state *state =
1480 tevent_req_data(req,
1481 struct dcerpc_do_bind_state);
1485 /* Ensure we have the correct type. */
1486 switch (pkt->ptype) {
1487 case DCERPC_PKT_BIND_ACK:
1488 case DCERPC_PKT_ALTER_RESP:
1489 if (!state->conn->features.bind_done) {
1490 if (pkt->u.bind_ack.max_recv_frag < 1234) {
1491 return NT_STATUS_RPC_PROTOCOL_ERROR;
1493 if (pkt->u.bind_ack.max_xmit_frag < 1234) {
1494 return NT_STATUS_RPC_PROTOCOL_ERROR;
1496 state->conn->features.max_recv_frag =
1497 pkt->u.bind_ack.max_recv_frag;
1498 state->conn->features.max_xmit_frag =
1499 pkt->u.bind_ack.max_xmit_frag;
1501 if (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) {
1502 state->conn->features.concurrent_multiplex = true;
1505 state->conn->features.bind_done = true;
1508 if (!state->conn->assoc->negotiate_done) {
1509 state->conn->assoc->negotiate_done = true;
1510 state->conn->assoc->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
1513 if (pkt->u.bind_ack.assoc_group_id != state->conn->assoc->assoc_group_id) {
1514 return NT_STATUS_RPC_PROTOCOL_ERROR;
1517 if (pkt->u.bind_ack.num_results > state->num_ctx) {
1518 return NT_STATUS_RPC_PROTOCOL_ERROR;
1521 state->remaining_pres = 0;
1523 if (state->proposed_hdr_signing) {
1524 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1525 state->sec->hdr_signing = true;
1529 for (i = 0; i < pkt->u.bind_ack.num_results; i++) {
1530 struct dcerpc_ack_ctx *ack = &pkt->u.bind_ack.ctx_list[i];
1532 if (i < state->num_pres) {
1533 state->pres[i]->negotiate.ack = *ack;
1537 if (ack->result != DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1541 state->conn->assoc->features = state->conn->assoc->client_features;
1542 state->conn->assoc->features &= ack->reason.negotiate;
1545 for (i = 0; i < state->num_pres; i++) {
1546 struct dcerpc_ack_ctx *ack = &state->pres[i]->negotiate.ack;
1549 if (ack->result != DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1553 ok = ndr_syntax_id_equal(&state->pres[i]->transfer,
1556 return NT_STATUS_RPC_PROTOCOL_ERROR;
1560 if (pkt->auth_length >= 8) {
1561 struct tevent_req *subreq;
1563 state->sec_in = data_blob_talloc(state,
1564 pkt->u.bind_ack.auth_info.data + 8,
1565 pkt->u.bind_ack.auth_info.length - 8);
1567 subreq = gensec_update_send(state, state->ev,
1570 if (tevent_req_nomem(subreq, req)) {
1571 return NT_STATUS_OK;
1573 tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
1574 return NT_STATUS_OK;
1577 tevent_req_done(req);
1578 return NT_STATUS_OK;
1580 //case DCERPC_PKT_ALTER_RESP:
1581 if (pkt->auth_length != 0) {
1582 return NT_STATUS_NOT_IMPLEMENTED;
1585 return NT_STATUS_NOT_IMPLEMENTED;
1588 /* Point the return values at the NDR data. */
1589 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
1591 if (pkt->auth_length) {
1592 /* We've already done integer wrap tests in
1593 * dcerpc_check_auth(). */
1594 payload.length = frag.length
1595 - DCERPC_RESPONSE_LENGTH
1597 - DCERPC_AUTH_TRAILER_LENGTH
1600 payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
1603 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1604 if (pkt->drep[0] & DCERPC_DREP_LE) {
1605 state->response.bigendian = false;
1607 state->response.bigendian = true;
1611 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
1612 (long unsigned int)frag.length,
1613 (long unsigned int)payload.length,
1614 (unsigned int)pad_len));
1617 * If this is the first reply, and the allocation hint is
1618 * reasonable, try and set up the reply_pdu DATA_BLOB to the
1622 if ((state->response.blob.length == 0) &&
1623 pkt->u.response.alloc_hint &&
1624 (pkt->u.response.alloc_hint < 15*1024*1024)) {
1625 ok = data_blob_realloc(state, &state->response.blob,
1626 pkt->u.response.alloc_hint);
1628 DEBUG(0, ("reply alloc hint %d too "
1629 "large to allocate\n",
1630 (int)pkt->u.response.alloc_hint));
1631 return NT_STATUS_NO_MEMORY;
1635 new_total = state->response.ofs + payload.length;
1637 if (new_total > 15 * 1024 *1024) {
1638 return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
1641 missing = new_total - state->response.blob.length;
1644 ok = data_blob_realloc(state, &state->response.blob,
1647 DEBUG(0, ("reply alloc hint %d too "
1648 "large to allocate\n",
1649 (int)pkt->u.response.alloc_hint));
1650 return NT_STATUS_NO_MEMORY;
1654 memcpy(state->response.blob.data + state->response.ofs,
1655 payload.data, payload.length);
1656 state->response.ofs += payload.length;
1658 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1659 tevent_req_done(req);//TODO
1660 return NT_STATUS_OK;
1662 return NT_STATUS_OK;
1664 return NT_STATUS_NOT_IMPLEMENTED;
1666 case DCERPC_PKT_FAULT:
1668 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1669 "code %s received from %s!\n",
1670 dcerpc_errstr(talloc_tos(),
1671 pkt->u.fault.status),
1674 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
1675 if (NT_STATUS_IS_OK(status)) {
1676 status = NT_STATUS_RPC_PROTOCOL_ERROR;
1679 tevent_req_nterror(req, status);//TODO
1680 return NT_STATUS_OK;
1682 DEBUG(0, ("Unknown packet type %u received from %s!\n",
1683 (unsigned int)pkt->ptype,
1685 return NT_STATUS_RPC_PROTOCOL_ERROR;
1688 return NT_STATUS_RPC_PROTOCOL_ERROR;
1691 NTSTATUS dcerpc_do_bind_recv(struct tevent_req *req)
1693 struct dcerpc_do_bind_state *state =
1694 tevent_req_data(req,
1695 struct dcerpc_do_bind_state);
1698 if (tevent_req_is_nterror(req, &status)) {
1699 tevent_req_received(req);
1703 if (!NT_STATUS_IS_OK(state->sec_status)) {
1704 status = state->sec_status;
1705 tevent_req_received(req);
1709 tevent_req_received(req);
1710 return NT_STATUS_OK;
1713 struct dcerpc_do_request_out_frag;
1715 struct dcerpc_do_request_state {
1716 struct tevent_context *ev;
1717 struct dcerpc_connection *conn;
1718 struct dcerpc_call *call;
1719 const struct GUID *object;
1722 const DATA_BLOB *blob;
1728 bool verify_bitmask1;
1729 bool verify_pcontext;
1731 struct dcerpc_do_request_out_frag *out_frag;
1739 struct dcerpc_do_request_out_frag {
1740 struct tevent_context *ev;
1741 struct dcerpc_connection *conn;
1742 struct tevent_req *req;
1745 struct iovec vector;
1746 struct tevent_req *subreq_wait1;
1747 struct tevent_req *subreq_wait2;
1750 static void dcerpc_do_request_cleanup(struct tevent_req *req,
1751 enum tevent_req_state req_state);
1753 static void dcerpc_do_request_verification_trailer(struct tevent_req *req);
1754 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
1755 void *private_data);
1757 static NTSTATUS dcerpc_do_request_handle_in_frag(void *private_data,
1758 struct ncacn_packet *pkt,
1761 struct tevent_req *dcerpc_do_request_send(TALLOC_CTX *mem_ctx,
1762 struct tevent_context *ev,
1763 struct dcerpc_connection *conn,
1764 struct dcerpc_call *call,
1765 const struct GUID *object,
1767 const DATA_BLOB *request,
1770 struct tevent_req *req;
1771 struct dcerpc_do_request_state *state;
1774 req = tevent_req_create(mem_ctx, &state,
1775 struct dcerpc_do_request_state);
1782 state->object = object;
1783 state->opnum = opnum;
1784 state->request.blob = request;
1785 state->request.bigendian = bigendian;
1787 dcerpc_do_request_verification_trailer(req);
1788 if (!tevent_req_is_in_progress(req)) {
1789 return tevent_req_post(req, ev);
1792 state->call->incoming.private_data = req;
1793 state->call->incoming.handler = dcerpc_do_request_handle_in_frag;
1794 DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
1796 tevent_req_set_cleanup_fn(req, dcerpc_do_request_cleanup);
1797 tevent_req_defer_callback(req, ev);
1799 ok = tevent_queue_add(state->conn->calls.out_queue,
1802 dcerpc_do_request_out_frag_next,
1805 tevent_req_nomem(NULL, req);
1806 return tevent_req_post(req, ev);
1812 static void dcerpc_do_request_cleanup(struct tevent_req *req,
1813 enum tevent_req_state req_state)
1815 struct dcerpc_do_request_state *state =
1816 tevent_req_data(req,
1817 struct dcerpc_do_request_state);
1819 if (state->out_frag != NULL) {
1820 state->out_frag->req = NULL;
1821 state->out_frag = NULL;
1824 if (state->call != NULL) {
1825 if (state->call == state->conn->calls.active) {
1826 state->conn->calls.active = NULL;
1828 ZERO_STRUCT(state->call->incoming);
1829 DLIST_REMOVE(state->conn->calls.list, state->call);
1834 static void dcerpc_do_request_verification_trailer(struct tevent_req *req)
1836 struct dcerpc_do_request_state *state =
1837 tevent_req_data(req,
1838 struct dcerpc_do_request_state);
1839 struct dcerpc_sec_verification_trailer *t;
1840 struct dcerpc_sec_vt *c = NULL;
1841 struct ndr_push *ndr = NULL;
1842 enum ndr_err_code ndr_err;
1846 if (state->call->sec->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1850 t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1851 if (tevent_req_nomem(t, req)) {
1855 if (!state->call->sec->verified_bitmask1) {
1856 t->commands = talloc_realloc(t, t->commands,
1857 struct dcerpc_sec_vt,
1858 t->count.count + 1);
1859 if (tevent_req_nomem(t->commands, req)) {
1862 c = &t->commands[t->count.count++];
1865 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1866 if (state->call->sec->client_hdr_signing) {
1867 c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1869 state->verify_bitmask1 = true;
1872 if (!state->call->pres->verified_pcontext) {
1873 t->commands = talloc_realloc(t, t->commands,
1874 struct dcerpc_sec_vt,
1875 t->count.count + 1);
1876 if (tevent_req_nomem(t->commands, req)) {
1879 c = &t->commands[t->count.count++];
1882 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1883 c->u.pcontext.abstract_syntax = state->call->pres->table->syntax_id;
1884 c->u.pcontext.transfer_syntax = state->call->pres->transfer;
1886 state->verify_pcontext = true;
1889 if (!state->call->sec->hdr_signing) {
1890 t->commands = talloc_realloc(t, t->commands,
1891 struct dcerpc_sec_vt,
1892 t->count.count + 1);
1893 if (tevent_req_nomem(t->commands, req)) {
1896 c = &t->commands[t->count.count++];
1899 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1900 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1901 if (state->request.bigendian) {
1902 c->u.header2.drep[0] = 0;
1904 c->u.header2.drep[0] = DCERPC_DREP_LE;
1906 c->u.header2.drep[1] = 0;
1907 c->u.header2.drep[2] = 0;
1908 c->u.header2.drep[3] = 0;
1909 c->u.header2.call_id = state->call->call_id;
1910 c->u.header2.context_id = 0;
1911 c->u.header2.opnum = state->opnum;
1914 if (t->count.count == 0) {
1919 c = &t->commands[t->count.count - 1];
1920 c->command |= DCERPC_SEC_VT_COMMAND_END;
1922 if (DEBUGLEVEL >= 10) {
1923 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1926 ndr = ndr_push_init_ctx(state);
1927 if (tevent_req_nomem(ndr, req)) {
1931 //TODO if (state->request.bigendian)
1933 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1934 NDR_SCALARS | NDR_BUFFERS,
1936 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1937 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1938 tevent_req_nterror(req, status);
1941 state->request.trailer = ndr_push_blob(ndr);
1943 align = state->request.blob->length & 0x3;
1950 const uint8_t zeros[4] = { 0, };
1952 ok = data_blob_append(ndr, &state->request.trailer, zeros, pad);
1954 tevent_req_oom(req);
1958 /* move the padding to the start */
1959 p = state->request.trailer.data;
1960 memmove(p + pad, p, state->request.trailer.length - pad);
1967 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq);
1968 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq);
1969 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq);
1971 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
1974 struct dcerpc_do_request_state *state =
1975 tevent_req_data(req,
1976 struct dcerpc_do_request_state);
1977 struct dcerpc_do_request_out_frag *frag;
1978 size_t hdr_len = DCERPC_REQUEST_LENGTH;
1984 size_t data_thistime;
1985 size_t trailer_left;
1986 size_t trailer_thistime = 0;
1988 size_t total_thistime;
1990 union dcerpc_payload u;
1992 struct tevent_req *subreq;
1993 bool use_trans = true;
1995 if (state->object) {
1996 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
2001 * the fragment belongs to the connection instead of the request
2002 * because it has to remain in case the request is canceled
2004 frag = talloc_zero(state->conn, struct dcerpc_do_request_out_frag);
2005 if (tevent_req_nomem(frag, req)) {
2008 frag->ev = state->ev;
2009 frag->conn = state->conn;
2011 state->out_frag = frag;
2013 data_left = state->request.blob->length - state->request.ofs;
2014 trailer_left = state->request.trailer.length - state->request.trailer_ofs;
2015 total_left = data_left + trailer_left;
2016 if (total_left < data_left || total_left < trailer_left) {
2017 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2021 status = dcerpc_guess_pdu_sizes(state->call->sec,
2022 hdr_len, total_left,
2023 state->conn->features.max_xmit_frag,
2026 &frag_len, &auth_len, &pad_len);
2027 if (!NT_STATUS_IS_OK(status)) {
2028 tevent_req_nterror(req, status);
2032 if (state->request.ofs == 0) {
2033 flags |= DCERPC_PFC_FLAG_FIRST;
2036 if (total_thistime == total_left) {
2037 flags |= DCERPC_PFC_FLAG_LAST;
2040 data_thistime = MIN(total_thistime, data_left);
2041 if (data_thistime < total_thistime) {
2042 trailer_thistime = total_thistime - data_thistime;
2045 ZERO_STRUCT(u.request);
2047 u.request.alloc_hint = total_left;
2048 u.request.context_id = state->call->pres->context_id;
2049 u.request.opnum = state->opnum;
2050 if (state->object) {
2051 u.request.object.object = *state->object;
2053 //TODO pass state->request.bigendian
2054 status = dcerpc_ncacn_packet_blob(frag,
2058 state->call->call_id,
2061 if (!NT_STATUS_IS_OK(status)) {
2062 tevent_req_nterror(req, status);
2066 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2067 * compute it right for requests because the auth trailer is missing
2069 dcerpc_set_frag_length(&frag->blob, frag_len);
2071 if (data_thistime > 0) {
2072 const uint8_t *data_ptr;
2074 data_ptr = state->request.blob->data;
2075 data_ptr += state->request.ofs;
2077 /* Copy in the data. */
2078 ok = data_blob_append(frag, &frag->blob,
2079 data_ptr, data_thistime);
2081 tevent_req_oom(req);
2085 state->request.ofs += data_thistime;
2088 if (trailer_thistime > 0) {
2089 const uint8_t *trailer_ptr;
2091 trailer_ptr = state->request.trailer.data;
2092 trailer_ptr += state->request.trailer_ofs;
2094 /* Copy in the data. */
2095 ok = data_blob_append(frag, &frag->blob,
2096 trailer_ptr, trailer_thistime);
2098 tevent_req_oom(req);
2102 state->request.trailer_ofs += trailer_thistime;
2105 switch (state->call->sec->auth_level) {
2106 case DCERPC_AUTH_LEVEL_NONE:
2107 case DCERPC_AUTH_LEVEL_CONNECT:
2108 case DCERPC_AUTH_LEVEL_PACKET:
2110 case DCERPC_AUTH_LEVEL_INTEGRITY:
2111 case DCERPC_AUTH_LEVEL_PRIVACY:
2112 status = dcerpc_response_auth_blob(state->call->sec,
2115 if (!NT_STATUS_IS_OK(status)) {
2116 tevent_req_nterror(req, status);
2121 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2125 frag->is_last = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2127 if (!frag->is_last) {
2131 if (frag->conn->transport.use_trans_fn == NULL) {
2135 if (frag->conn->loop.subreq != NULL) {
2139 if (frag->conn->features.concurrent_multiplex) {
2143 if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
2148 frag->subreq_wait1 = tevent_queue_wait_send(frag,
2150 frag->conn->transport.write_queue);
2151 if (tevent_req_nomem(req, frag->subreq_wait1)) {
2154 tevent_req_set_callback(frag->subreq_wait1,
2155 dcerpc_do_request_out_frag_trans_wait1,
2158 * we need to block reads until our write is
2159 * the next in the write queue.
2161 frag->conn->loop.subreq = frag->subreq_wait1;
2162 frag->conn->loop.ev = frag->ev;
2166 * We need to add a dcerpc_write_fragment_queue_send/recv()
2169 frag->vector.iov_base = frag->blob.data;
2170 frag->vector.iov_len = frag->blob.length;
2171 subreq = tstream_writev_queue_send(frag, frag->ev,
2172 frag->conn->transport.stream,
2173 frag->conn->transport.write_queue,
2175 if (tevent_req_nomem(subreq, req)) {
2178 tevent_req_set_callback(subreq,
2179 dcerpc_do_request_out_frag_done,
2183 frag->subreq_wait2 = tevent_queue_wait_send(frag,
2185 frag->conn->transport.write_queue);
2186 if (tevent_req_nomem(req, frag->subreq_wait2)) {
2189 tevent_req_set_callback(frag->subreq_wait2,
2190 dcerpc_do_request_out_frag_trans_wait2,
2194 if (!frag->is_last) {
2198 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2199 if (tevent_req_nterror(req, status)) {
2204 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq)
2206 struct dcerpc_do_request_out_frag *frag =
2207 tevent_req_callback_data(subreq,
2208 struct dcerpc_do_request_out_frag);
2209 struct tevent_req *req = frag->req;
2214 * TODO; what if the caller has been free'ed?
2217 frag->subreq_wait1 = NULL;
2218 frag->conn->loop.subreq = NULL;
2220 ok = tevent_queue_wait_recv(subreq);
2222 status = NT_STATUS_INTERNAL_ERROR;
2225 tevent_req_nterror(req, status);
2227 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2231 if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
2233 * We added 3 entries into the queue,
2234 * wait1, writev and wait2.
2236 * There's more to write, we should not block
2237 * further writev calls for a trans call.
2239 * The wait2 stage will trigger the read.
2241 TALLOC_FREE(subreq);
2246 * we don't need wait2 anymore, we're sure that
2247 * we'll do a trans call.
2249 TALLOC_FREE(frag->subreq_wait2);
2251 status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
2252 if (!NT_STATUS_IS_OK(status)) {
2255 tevent_req_nterror(req, status);
2257 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2261 /* we free subreq after tstream_cli_np_use_trans */
2262 TALLOC_FREE(subreq);
2264 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2265 if (!NT_STATUS_IS_OK(status)) {
2268 tevent_req_nterror(req, status);
2270 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2275 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq)
2277 struct dcerpc_do_request_out_frag *frag =
2278 tevent_req_callback_data(subreq,
2279 struct dcerpc_do_request_out_frag);
2280 struct tevent_req *req = frag->req;
2286 * If the caller has been free'ed, we have should
2287 * ignore any errors and just free 'frag'
2290 struct dcerpc_do_request_state *state =
2291 tevent_req_data(req,
2292 struct dcerpc_do_request_state);
2294 state->out_frag = NULL;
2297 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2298 TALLOC_FREE(subreq);
2301 status = map_nt_error_from_unix_common(sys_errno);
2303 tevent_req_nterror(req, status);
2308 if (frag->subreq_wait2 != NULL) {
2312 if (frag->is_last) {
2322 dcerpc_do_request_out_frag_next(req, NULL);
2325 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq)
2327 struct dcerpc_do_request_out_frag *frag =
2328 tevent_req_callback_data(subreq,
2329 struct dcerpc_do_request_out_frag);
2330 struct tevent_req *req = frag->req;
2334 frag->subreq_wait2 = NULL;
2336 ok = tevent_queue_wait_recv(subreq);
2338 status = NT_STATUS_INTERNAL_ERROR;
2341 tevent_req_nterror(req, status);
2343 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2347 TALLOC_FREE(subreq);
2349 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2350 if (!NT_STATUS_IS_OK(status)) {
2353 tevent_req_nterror(req, status);
2355 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2361 /* we need to wait for incoming pdus */
2364 static NTSTATUS dcerpc_do_request_handle_in_frag(void *private_data,
2365 struct ncacn_packet *pkt,
2368 struct tevent_req *req =
2369 talloc_get_type_abort(private_data,
2371 struct dcerpc_do_request_state *state =
2372 tevent_req_data(req,
2373 struct dcerpc_do_request_state);
2382 /* Ensure we have the correct type. */
2383 switch (pkt->ptype) {
2384 case DCERPC_PKT_RESPONSE:
2386 /* Here's where we deal with incoming sign/seal. */
2387 error = dcerpc_check_pdu_auth(state->call->sec,
2389 &pkt->u.response.stub_and_verifier,
2390 DCERPC_RESPONSE_LENGTH,
2392 if (!NT_STATUS_IS_OK(error)) {
2396 if (!state->got_first) {
2397 state->got_first = true;
2399 if (pkt->drep[0] & DCERPC_DREP_LE) {
2400 state->response.bigendian = false;
2402 state->response.bigendian = true;
2405 if (state->verify_bitmask1) {
2406 state->call->sec->verified_bitmask1 = true;
2409 if (state->verify_pcontext) {
2410 state->call->pres->verified_pcontext = true;
2414 if (state->response.bigendian) {
2415 if (pkt->drep[0] != 0) {
2416 return NT_STATUS_RPC_PROTOCOL_ERROR;
2419 if (pkt->drep[0] != DCERPC_DREP_LE) {
2420 return NT_STATUS_RPC_PROTOCOL_ERROR;
2423 if (pkt->drep[1] != 0) {
2424 return NT_STATUS_RPC_PROTOCOL_ERROR;
2426 if (pkt->drep[2] != 0) {
2427 return NT_STATUS_RPC_PROTOCOL_ERROR;
2429 if (pkt->drep[3] != 0) {
2430 return NT_STATUS_RPC_PROTOCOL_ERROR;
2433 if (pkt->u.response.context_id != state->call->pres->context_id) {
2434 return NT_STATUS_RPC_PROTOCOL_ERROR;
2437 if (frag.length < DCERPC_RESPONSE_LENGTH + pad_len) {
2438 return NT_STATUS_RPC_PROTOCOL_ERROR;
2441 /* Point the return values at the NDR data. */
2442 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
2444 if (pkt->auth_length) {
2445 /* We've already done integer wrap tests in
2446 * dcerpc_check_auth(). */
2447 payload.length = frag.length
2448 - DCERPC_RESPONSE_LENGTH
2450 - DCERPC_AUTH_TRAILER_LENGTH
2453 payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
2456 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
2457 (long unsigned int)frag.length,
2458 (long unsigned int)payload.length,
2459 (unsigned int)pad_len));
2462 * If this is the first reply, and the allocation hint is
2463 * reasonable, try and set up the reply_pdu DATA_BLOB to the
2467 if ((state->response.blob.length == 0) &&
2468 pkt->u.response.alloc_hint &&
2469 (pkt->u.response.alloc_hint < 15*1024*1024)) {
2470 ok = data_blob_realloc(state, &state->response.blob,
2471 pkt->u.response.alloc_hint);
2473 DEBUG(0, ("reply alloc hint %d too "
2474 "large to allocate\n",
2475 (int)pkt->u.response.alloc_hint));
2476 return NT_STATUS_NO_MEMORY;
2480 new_total = state->response.ofs + payload.length;
2482 if (new_total > 15 * 1024 *1024) {
2483 return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
2486 missing = new_total - state->response.blob.length;
2489 ok = data_blob_realloc(state, &state->response.blob,
2492 DEBUG(0, ("reply alloc hint %d too "
2493 "large to allocate\n",
2494 (int)pkt->u.response.alloc_hint));
2495 return NT_STATUS_NO_MEMORY;
2499 memcpy(state->response.blob.data + state->response.ofs,
2500 payload.data, payload.length);
2501 state->response.ofs += payload.length;
2503 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
2504 tevent_req_done(req);//TODO
2505 return NT_STATUS_OK;
2508 return dcerpc_connection_loop_restart(state->conn, state->ev);
2510 case DCERPC_PKT_FAULT:
2512 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
2513 "code %s received from %s!\n",
2514 dcerpc_errstr(talloc_tos(),
2515 pkt->u.fault.status),
2518 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
2519 if (NT_STATUS_IS_OK(status)) {
2520 status = NT_STATUS_RPC_PROTOCOL_ERROR;
2523 tevent_req_nterror(req, status);//TODO
2524 return NT_STATUS_OK;
2526 DEBUG(0, ("Unknown packet type %u received from %s!\n",
2527 (unsigned int)pkt->ptype,
2529 return NT_STATUS_RPC_PROTOCOL_ERROR;
2533 NTSTATUS dcerpc_do_request_recv(struct tevent_req *req,
2534 TALLOC_CTX *mem_ctx,
2535 DATA_BLOB *response,
2538 struct dcerpc_do_request_state *state =
2539 tevent_req_data(req,
2540 struct dcerpc_do_request_state);
2543 if (tevent_req_is_nterror(req, &status)) {
2544 tevent_req_received(req);
2548 /* return data to caller and assign it ownership of memory */
2549 response->data = talloc_move(mem_ctx, &state->response.blob.data);
2550 response->length = state->response.blob.length;
2551 *bigendian = state->response.bigendian;
2553 tevent_req_received(req);
2554 return NT_STATUS_OK;