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 data = data_blob_const(raw_pkt->data + header_size,
609 pkt_trailer->length - auth_length);
610 full_pkt = data_blob_const(raw_pkt->data,
611 raw_pkt->length - auth_info.credentials.length);
613 switch (sec->auth_type) {
614 case DCERPC_AUTH_TYPE_NONE:
615 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
621 switch (sec->auth_level) {
622 case DCERPC_AUTH_LEVEL_PRIVACY:
623 /* Data portion is encrypted. */
624 status = gensec_unseal_packet(sec->gensec,
629 &auth_info.credentials);
632 case DCERPC_AUTH_LEVEL_INTEGRITY:
633 /* Data is signed. */
634 status = gensec_check_packet(sec->gensec,
639 &auth_info.credentials);
642 return NT_STATUS_INVALID_PARAMETER;
644 /* TODO: remove later
645 * this is still needed because in the server code the
646 * pkt_trailer actually has a copy of the raw data, and they
647 * are still both used in later calls */
648 if (sec->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
649 memcpy(pkt_trailer->data, data.data, data.length);
652 *pad_len = auth_info.auth_pad_length;
653 data_blob_free(&auth_info.credentials);
657 static void dcerpc_connection_loop(struct tevent_req *subreq);
659 static NTSTATUS dcerpc_connection_loop_restart(struct dcerpc_connection *conn,
660 struct tevent_context *ev)
663 return NT_STATUS_INVALID_PARAMETER; // TODO...
666 if (conn->loop.subreq) {
667 if (conn->loop.ev != ev) {
668 return NT_STATUS_INVALID_PARAMETER; // TODO...
673 if (conn->calls.list == NULL) {
674 conn->loop.ev = NULL;
678 conn->loop.subreq = dcerpc_read_ncacn_packet_send(conn,
680 conn->transport.stream);
681 if (conn->loop.subreq == NULL) {
682 return NT_STATUS_NO_MEMORY;
684 tevent_req_set_callback(conn->loop.subreq, dcerpc_connection_loop, conn);
689 static void dcerpc_connection_loop(struct tevent_req *subreq)
691 struct dcerpc_connection *conn =
692 tevent_req_callback_data(subreq,
693 struct dcerpc_connection);
695 struct ncacn_packet *pkt;
697 struct dcerpc_call *call;
698 bool valid_type = false;
699 bool allow_fragments = false;
701 conn->loop.subreq = NULL;
703 error = dcerpc_read_ncacn_packet_recv(subreq, subreq, &pkt, &pdu);
704 if (!NT_STATUS_IS_OK(error)) {
706 // disconnect and notify pending calls
710 if (DEBUGLEVEL >= 10) {
711 NDR_PRINT_DEBUG(ncacn_packet, pkt);
714 switch (pkt->ptype) {
715 case DCERPC_PKT_REQUEST:
716 /* Ordinary request. */
718 allow_fragments = true;
721 case DCERPC_PKT_PING:
722 /* Connectionless is server alive ? */
725 case DCERPC_PKT_RESPONSE:
726 /* Ordinary reply. */
728 allow_fragments = true;
731 case DCERPC_PKT_FAULT:
732 /* Fault in processing of call. */
736 case DCERPC_PKT_WORKING:
737 /* Connectionless reply to a ping when server busy. */
740 case DCERPC_PKT_NOCALL:
741 /* Connectionless reply to a ping when server has lost part of clients call. */
744 case DCERPC_PKT_REJECT:
745 /* Refuse a request with a code. */
751 case DCERPC_PKT_CL_CANCEL:
754 case DCERPC_PKT_FACK:
757 case DCERPC_PKT_CANCEL_ACK:
758 /* Server ACK to client cancel request. */
761 case DCERPC_PKT_BIND:
762 /* Bind to interface. */
766 case DCERPC_PKT_BIND_ACK:
767 /* Server ack of bind. */
771 case DCERPC_PKT_BIND_NAK:
772 /* Server nack of bind. */
776 case DCERPC_PKT_ALTER:
781 case DCERPC_PKT_ALTER_RESP:
782 /* Reply to alter auth. */
786 case DCERPC_PKT_AUTH3:
787 /* not the real name! this is undocumented! */
791 case DCERPC_PKT_SHUTDOWN:
792 /* Server to client request to shutdown. */
796 case DCERPC_PKT_CO_CANCEL:
797 /* Connection-oriented cancel request. */
801 case DCERPC_PKT_ORPHANED:
802 /* Client telling server it's aborting a partially sent request or telling server to stop sending replies. */
807 /* RTS packets used in ncacn_http */
813 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
817 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
818 if (!allow_fragments) {
820 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
825 if (conn->calls.active != NULL) {
827 if (pkt->call_id != conn->calls.active->call_id) {
829 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
833 if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) {
835 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
839 call = conn->calls.active;
841 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
842 conn->calls.active = NULL;
845 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
847 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
851 call = conn->calls.list;
854 for (call = conn->calls.list; call; call = call->next) {
855 if (call->call_id == pkt->call_id) {
861 call = conn->calls.new_call;
866 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
870 if (call->incoming.handler == NULL) {
872 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
876 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
877 conn->calls.active = call;
881 // reassemble and return
884 error = call->incoming.handler(call->incoming.private_data, pkt, pdu);
886 if (!NT_STATUS_IS_OK(error)) {
887 // disconnect and notify pending calls
891 if (conn->calls.new_call == NULL) {
892 conn->loop.ev = NULL;
896 error = dcerpc_connection_loop_restart(conn, conn->loop.ev);
897 if (!NT_STATUS_IS_OK(error)) {
898 // disconnect and notify pending calls
903 struct dcerpc_do_bind_out_frag;
905 struct dcerpc_do_bind_state {
906 struct tevent_context *ev;
907 struct dcerpc_connection *conn;
908 struct dcerpc_call *call;
909 struct dcerpc_security *sec;
910 bool proposed_hdr_signing;
914 struct dcerpc_do_bind_out_frag *out_frag;
916 struct dcerpc_presentation **pres;
917 uint32_t remaining_pres;
920 struct dcerpc_ctx_list *ctx_list;
921 struct ndr_syntax_id features;
924 struct dcerpc_do_bind_out_frag {
925 struct tevent_context *ev;
926 struct dcerpc_connection *conn;
927 struct tevent_req *req;
928 enum dcerpc_pkt_type ptype;
931 struct tevent_req *subreq_wait1;
932 struct tevent_req *subreq_wait2;
935 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
936 enum tevent_req_state req_state);
938 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq);
939 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq);
941 static NTSTATUS dcerpc_do_bind_handle_in_frag(void *private_data,
942 struct ncacn_packet *pkt,
945 struct tevent_req *dcerpc_do_bind_send(TALLOC_CTX *mem_ctx,
946 struct tevent_context *ev,
947 struct dcerpc_connection *conn,
948 struct dcerpc_call *call,
949 struct dcerpc_security *sec,
951 struct dcerpc_presentation **pres)
953 struct tevent_req *req;
954 struct dcerpc_do_bind_state *state;
955 struct tevent_req *subreq;
957 req = tevent_req_create(mem_ctx, &state,
958 struct dcerpc_do_bind_state);
966 state->num_pres = num_pres;
969 state->call->incoming.private_data = req;
970 state->call->incoming.handler = dcerpc_do_bind_handle_in_frag;
971 DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
973 tevent_req_set_cleanup_fn(req, dcerpc_do_bind_cleanup);
974 tevent_req_defer_callback(req, ev);
976 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
977 subreq = gensec_update_send(state, ev,
980 if (tevent_req_nomem(subreq, req)) {
981 return tevent_req_post(req, ev);
983 tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
988 state->sec_status = NT_STATUS_OK;
990 subreq = tevent_queue_wait_send(state, state->ev,
991 state->conn->calls.out_queue);
992 if (tevent_req_nomem(subreq, req)) {
993 return tevent_req_post(req, ev);
995 tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
1000 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
1001 enum tevent_req_state req_state)
1003 struct dcerpc_do_bind_state *state =
1004 tevent_req_data(req,
1005 struct dcerpc_do_bind_state);
1007 if (state->out_frag != NULL) {
1008 state->out_frag->req = NULL;
1009 state->out_frag = NULL;
1012 if (state->call != NULL) {
1013 ZERO_STRUCT(state->call->incoming);
1014 DLIST_REMOVE(state->conn->calls.list, state->call);
1019 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq)
1021 struct tevent_req *req =
1022 tevent_req_callback_data(subreq,
1024 struct dcerpc_do_bind_state *state =
1025 tevent_req_data(req,
1026 struct dcerpc_do_bind_state);
1029 data_blob_free(&state->sec_out);
1030 status = gensec_update_recv(subreq, state, &state->sec_out);
1031 TALLOC_FREE(subreq);
1032 data_blob_free(&state->sec_in);
1033 state->sec_status = status;
1034 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1035 status = NT_STATUS_OK;
1037 if (!NT_STATUS_IS_OK(status)) {
1038 tevent_req_nterror(req, status);
1042 if (NT_STATUS_IS_OK(state->sec_status) &&
1043 state->sec_out.length == 0)
1045 tevent_req_done(req);
1049 if (state->sec->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1050 state->sec->client_hdr_signing =
1051 gensec_have_feature(state->sec->gensec,
1052 GENSEC_FEATURE_SIGN_PKT_HEADER);
1055 subreq = tevent_queue_wait_send(state, state->ev,
1056 state->conn->calls.out_queue);
1057 if (tevent_req_nomem(subreq, req)) {
1060 tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
1063 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq);
1064 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq);
1065 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq);
1067 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq)
1069 struct tevent_req *req =
1070 tevent_req_callback_data(subreq,
1072 struct dcerpc_do_bind_state *state =
1073 tevent_req_data(req,
1074 struct dcerpc_do_bind_state);
1075 struct dcerpc_do_bind_out_frag *frag;
1076 size_t auth_len = 0;
1078 DATA_BLOB auth_info = data_blob_null;
1079 uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1080 union dcerpc_payload u;
1082 bool require_ack = false;
1083 bool use_trans = true;
1086 ok = tevent_queue_wait_recv(subreq);
1088 //status = NT_STATUS_INTERNAL_ERROR;
1089 tevent_req_oom(req);
1092 TALLOC_FREE(subreq);
1095 * the fragment belongs to the connection instead of the request
1096 * because it has to remain in case the request is canceled
1098 frag = talloc_zero(state->conn, struct dcerpc_do_bind_out_frag);
1099 if (tevent_req_nomem(frag, req)) {
1102 frag->ev = state->ev;
1103 frag->conn = state->conn;
1105 state->out_frag = frag;
1107 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1108 if (state->sec->client_hdr_signing &&
1109 !state->proposed_hdr_signing)
1111 state->proposed_hdr_signing = true;
1112 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1117 //TODO : DCERPC_PFC_FLAG_CONC_MPX
1119 //TODO: remaining_pres
1121 if (!state->conn->features.bind_done) {
1122 frag->ptype = DCERPC_PKT_BIND;
1123 } else if (require_ack) {
1124 frag->ptype = DCERPC_PKT_ALTER;
1125 } else if (state->remaining_pres > 0) {
1126 frag->ptype = DCERPC_PKT_ALTER;
1127 } else if (!NT_STATUS_IS_OK(state->sec_status)) {
1128 frag->ptype = DCERPC_PKT_ALTER;
1130 frag->ptype = DCERPC_PKT_AUTH3;
1133 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1134 status = dcerpc_auth_blob(frag,
1135 state->sec->auth_type,
1136 state->sec->auth_level,
1137 0, /* auth_pad_length */
1138 state->sec->context_id, /* auth_context_id */
1141 if (!NT_STATUS_IS_OK(status)) {
1142 tevent_req_nterror(req, status);
1146 auth_len = auth_info.length;
1149 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1153 state->num_ctx = state->num_pres;
1154 if (!state->conn->assoc->negotiate_done) {
1155 state->num_ctx += 1;
1158 state->ctx_list = talloc_zero_array(frag,
1159 struct dcerpc_ctx_list,
1161 if (tevent_req_nomem(state->ctx_list, req)) {
1165 for (i=0; i < state->num_pres; i++) {
1166 state->ctx_list[i] = state->pres[i]->negotiate.req;
1169 if (!state->conn->assoc->negotiate_done) {
1170 state->features = dcerpc_construct_bind_time_features(
1171 state->conn->assoc->client_features);
1173 state->ctx_list[i].context_id = state->conn->next_pres_context_id;
1175 state->ctx_list[i].abstract_syntax =
1176 state->ctx_list[i-1].abstract_syntax;
1178 state->ctx_list[i].num_transfer_syntaxes = 1;
1179 state->ctx_list[i].transfer_syntaxes = &state->features;
1182 switch (frag->ptype) {
1183 case DCERPC_PKT_BIND:
1184 case DCERPC_PKT_ALTER:
1185 u.bind.max_xmit_frag = state->conn->features.max_xmit_frag;
1186 u.bind.max_recv_frag = state->conn->features.max_recv_frag;
1187 u.bind.assoc_group_id = state->conn->assoc->assoc_group_id;
1188 u.bind.num_contexts = state->num_ctx;
1189 u.bind.ctx_list = state->ctx_list;
1190 u.bind.auth_info = auth_info;
1193 case DCERPC_PKT_AUTH3:
1195 u.auth3.auth_info = auth_info;
1198 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1202 status = dcerpc_ncacn_packet_blob(frag,
1206 state->call->call_id,
1209 if (!NT_STATUS_IS_OK(status)) {
1210 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1211 tevent_req_nterror(req, status);
1215 if (frag->ptype == DCERPC_PKT_AUTH3) {
1219 if (frag->conn->transport.use_trans_fn == NULL) {
1223 if (frag->conn->loop.subreq != NULL) {
1227 if (frag->conn->features.concurrent_multiplex) {
1231 if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
1236 frag->subreq_wait1 = tevent_queue_wait_send(frag,
1238 frag->conn->transport.write_queue);
1239 if (tevent_req_nomem(req, frag->subreq_wait1)) {
1242 tevent_req_set_callback(frag->subreq_wait1,
1243 dcerpc_do_bind_out_frag_trans_wait1,
1246 * we need to block reads until our write is
1247 * the next in the write queue.
1249 frag->conn->loop.subreq = frag->subreq_wait1;
1250 frag->conn->loop.ev = frag->ev;
1254 * We need to add a dcerpc_write_fragment_queue_send/recv()
1257 frag->vector.iov_base = frag->blob.data;
1258 frag->vector.iov_len = frag->blob.length;
1259 subreq = tstream_writev_queue_send(frag, frag->ev,
1260 frag->conn->transport.stream,
1261 frag->conn->transport.write_queue,
1263 if (tevent_req_nomem(subreq, req)) {
1266 tevent_req_set_callback(subreq,
1267 dcerpc_do_bind_out_frag_done,
1271 frag->subreq_wait2 = tevent_queue_wait_send(frag,
1273 frag->conn->transport.write_queue);
1274 if (tevent_req_nomem(req, frag->subreq_wait2)) {
1277 tevent_req_set_callback(frag->subreq_wait2,
1278 dcerpc_do_bind_out_frag_trans_wait2,
1282 if (frag->ptype == DCERPC_PKT_AUTH3) {
1286 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1287 if (tevent_req_nterror(req, status)) {
1292 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq)
1294 struct dcerpc_do_bind_out_frag *frag =
1295 tevent_req_callback_data(subreq,
1296 struct dcerpc_do_bind_out_frag);
1297 struct tevent_req *req = frag->req;
1302 * TODO; what if the caller has been free'ed?
1305 frag->subreq_wait1 = NULL;
1306 frag->conn->loop.subreq = NULL;
1308 ok = tevent_queue_wait_recv(subreq);
1310 status = NT_STATUS_INTERNAL_ERROR;
1313 tevent_req_nterror(req, status);
1315 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1319 if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
1321 * We added 3 entries into the queue,
1322 * wait1, writev and wait2.
1324 * There's more to write, we should not block
1325 * further writev calls for a trans call.
1327 * The wait2 stage will trigger the read.
1329 TALLOC_FREE(subreq);
1334 * we don't need wait2 anymore, we're sure that
1335 * we'll do a trans call.
1337 TALLOC_FREE(frag->subreq_wait2);
1339 status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
1340 if (!NT_STATUS_IS_OK(status)) {
1343 tevent_req_nterror(req, status);
1345 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1349 /* we free subreq after tstream_cli_np_use_trans */
1350 TALLOC_FREE(subreq);
1352 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1353 if (!NT_STATUS_IS_OK(status)) {
1356 tevent_req_nterror(req, status);
1358 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1363 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq)
1365 struct dcerpc_do_bind_out_frag *frag =
1366 tevent_req_callback_data(subreq,
1367 struct dcerpc_do_bind_out_frag);
1368 struct tevent_req *req = frag->req;
1374 * If the caller has been free'ed, we have should
1375 * ignore any errors and just free 'frag'
1378 struct dcerpc_do_bind_state *state =
1379 tevent_req_data(req,
1380 struct dcerpc_do_bind_state);
1382 state->out_frag = NULL;
1385 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1386 TALLOC_FREE(subreq);
1389 status = map_nt_error_from_unix_common(sys_errno);
1391 tevent_req_nterror(req, status);
1396 if (frag->ptype == DCERPC_PKT_AUTH3) {
1401 tevent_req_done(req);
1405 if (frag->subreq_wait2 != NULL) {
1411 /* we need to wait for incoming pdus */
1414 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq)
1416 struct dcerpc_do_bind_out_frag *frag =
1417 tevent_req_callback_data(subreq,
1418 struct dcerpc_do_bind_out_frag);
1419 struct tevent_req *req = frag->req;
1423 frag->subreq_wait2 = NULL;
1425 ok = tevent_queue_wait_recv(subreq);
1427 status = NT_STATUS_INTERNAL_ERROR;
1430 tevent_req_nterror(req, status);
1432 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1436 TALLOC_FREE(subreq);
1438 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1439 if (!NT_STATUS_IS_OK(status)) {
1442 tevent_req_nterror(req, status);
1444 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1450 /* we need to wait for incoming pdus */
1453 static NTSTATUS dcerpc_do_bind_handle_in_frag(void *private_data,
1454 struct ncacn_packet *pkt,
1457 struct tevent_req *req =
1458 talloc_get_type_abort(private_data,
1460 struct dcerpc_do_bind_state *state =
1461 tevent_req_data(req,
1462 struct dcerpc_do_bind_state);
1466 /* Ensure we have the correct type. */
1467 switch (pkt->ptype) {
1468 case DCERPC_PKT_BIND_ACK:
1469 case DCERPC_PKT_ALTER_RESP:
1470 if (!state->conn->features.bind_done) {
1471 if (pkt->u.bind_ack.max_recv_frag < 1234) {
1472 return NT_STATUS_RPC_PROTOCOL_ERROR;
1474 if (pkt->u.bind_ack.max_xmit_frag < 1234) {
1475 return NT_STATUS_RPC_PROTOCOL_ERROR;
1477 state->conn->features.max_recv_frag =
1478 pkt->u.bind_ack.max_recv_frag;
1479 state->conn->features.max_xmit_frag =
1480 pkt->u.bind_ack.max_xmit_frag;
1482 if (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) {
1483 state->conn->features.concurrent_multiplex = true;
1486 state->conn->features.bind_done = true;
1489 if (!state->conn->assoc->negotiate_done) {
1490 state->conn->assoc->negotiate_done = true;
1491 state->conn->assoc->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
1494 if (pkt->u.bind_ack.assoc_group_id != state->conn->assoc->assoc_group_id) {
1495 return NT_STATUS_RPC_PROTOCOL_ERROR;
1498 if (pkt->u.bind_ack.num_results > state->num_ctx) {
1499 return NT_STATUS_RPC_PROTOCOL_ERROR;
1502 if (state->proposed_hdr_signing) {
1503 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1504 state->sec->hdr_signing = true;
1508 for (i = 0; i < pkt->u.bind_ack.num_results; i++) {
1509 struct dcerpc_ack_ctx *ack = &pkt->u.bind_ack.ctx_list[i];
1511 if (i < state->num_pres) {
1512 state->pres[i]->negotiate.ack = *ack;
1516 if (ack->result != DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1520 state->conn->assoc->features = state->conn->assoc->client_features;
1521 state->conn->assoc->features &= ack->reason.negotiate;
1524 for (i = 0; i < state->num_pres; i++) {
1525 struct dcerpc_ack_ctx *ack = &state->pres[i]->negotiate.ack;
1528 if (ack->result != DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1532 ok = ndr_syntax_id_equal(&state->pres[i]->transfer,
1535 return NT_STATUS_RPC_PROTOCOL_ERROR;
1539 if (pkt->auth_length >= 8) {
1540 struct tevent_req *subreq;
1542 state->sec_in = data_blob_talloc(state,
1543 pkt->u.bind_ack.auth_info.data + 8,
1544 pkt->u.bind_ack.auth_info.length - 8);
1546 subreq = gensec_update_send(state, state->ev,
1549 if (tevent_req_nomem(subreq, req)) {
1550 return NT_STATUS_OK;
1552 tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
1553 return NT_STATUS_OK;
1556 tevent_req_done(req);
1557 return NT_STATUS_OK;
1559 //case DCERPC_PKT_ALTER_RESP:
1560 if (pkt->auth_length != 0) {
1561 return NT_STATUS_NOT_IMPLEMENTED;
1564 return NT_STATUS_NOT_IMPLEMENTED;
1567 /* Point the return values at the NDR data. */
1568 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
1570 if (pkt->auth_length) {
1571 /* We've already done integer wrap tests in
1572 * dcerpc_check_auth(). */
1573 payload.length = frag.length
1574 - DCERPC_RESPONSE_LENGTH
1576 - DCERPC_AUTH_TRAILER_LENGTH
1579 payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
1582 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1583 if (pkt->drep[0] & DCERPC_DREP_LE) {
1584 state->response.bigendian = false;
1586 state->response.bigendian = true;
1590 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
1591 (long unsigned int)frag.length,
1592 (long unsigned int)payload.length,
1593 (unsigned int)pad_len));
1596 * If this is the first reply, and the allocation hint is
1597 * reasonable, try and set up the reply_pdu DATA_BLOB to the
1601 if ((state->response.blob.length == 0) &&
1602 pkt->u.response.alloc_hint &&
1603 (pkt->u.response.alloc_hint < 15*1024*1024)) {
1604 ok = data_blob_realloc(state, &state->response.blob,
1605 pkt->u.response.alloc_hint);
1607 DEBUG(0, ("reply alloc hint %d too "
1608 "large to allocate\n",
1609 (int)pkt->u.response.alloc_hint));
1610 return NT_STATUS_NO_MEMORY;
1614 new_total = state->response.ofs + payload.length;
1616 if (new_total > 15 * 1024 *1024) {
1617 return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
1620 missing = new_total - state->response.blob.length;
1623 ok = data_blob_realloc(state, &state->response.blob,
1626 DEBUG(0, ("reply alloc hint %d too "
1627 "large to allocate\n",
1628 (int)pkt->u.response.alloc_hint));
1629 return NT_STATUS_NO_MEMORY;
1633 memcpy(state->response.blob.data + state->response.ofs,
1634 payload.data, payload.length);
1635 state->response.ofs += payload.length;
1637 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1638 tevent_req_done(req);//TODO
1639 return NT_STATUS_OK;
1641 return NT_STATUS_OK;
1643 return NT_STATUS_NOT_IMPLEMENTED;
1645 case DCERPC_PKT_FAULT:
1647 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1648 "code %s received from %s!\n",
1649 dcerpc_errstr(talloc_tos(),
1650 pkt->u.fault.status),
1653 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
1654 if (NT_STATUS_IS_OK(status)) {
1655 status = NT_STATUS_RPC_PROTOCOL_ERROR;
1658 tevent_req_nterror(req, status);//TODO
1659 return NT_STATUS_OK;
1661 DEBUG(0, ("Unknown packet type %u received from %s!\n",
1662 (unsigned int)pkt->ptype,
1664 return NT_STATUS_RPC_PROTOCOL_ERROR;
1667 return NT_STATUS_RPC_PROTOCOL_ERROR;
1670 NTSTATUS dcerpc_do_bind_recv(struct tevent_req *req)
1672 struct dcerpc_do_bind_state *state =
1673 tevent_req_data(req,
1674 struct dcerpc_do_bind_state);
1677 if (tevent_req_is_nterror(req, &status)) {
1678 tevent_req_received(req);
1682 if (!NT_STATUS_IS_OK(state->sec_status)) {
1683 status = state->sec_status;
1684 tevent_req_received(req);
1688 tevent_req_received(req);
1689 return NT_STATUS_OK;
1692 struct dcerpc_do_request_out_frag;
1694 struct dcerpc_do_request_state {
1695 struct tevent_context *ev;
1696 struct dcerpc_connection *conn;
1697 struct dcerpc_call *call;
1698 const struct GUID *object;
1701 const DATA_BLOB *blob;
1707 bool verify_bitmask1;
1708 bool verify_pcontext;
1710 struct dcerpc_do_request_out_frag *out_frag;
1718 struct dcerpc_do_request_out_frag {
1719 struct tevent_context *ev;
1720 struct dcerpc_connection *conn;
1721 struct tevent_req *req;
1724 struct iovec vector;
1725 struct tevent_req *subreq_wait1;
1726 struct tevent_req *subreq_wait2;
1729 static void dcerpc_do_request_cleanup(struct tevent_req *req,
1730 enum tevent_req_state req_state);
1732 static void dcerpc_do_request_verification_trailer(struct tevent_req *req);
1733 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
1734 void *private_data);
1736 static NTSTATUS dcerpc_do_request_handle_in_frag(void *private_data,
1737 struct ncacn_packet *pkt,
1740 struct tevent_req *dcerpc_do_request_send(TALLOC_CTX *mem_ctx,
1741 struct tevent_context *ev,
1742 struct dcerpc_connection *conn,
1743 struct dcerpc_call *call,
1744 const struct GUID *object,
1746 const DATA_BLOB *request,
1749 struct tevent_req *req;
1750 struct dcerpc_do_request_state *state;
1753 req = tevent_req_create(mem_ctx, &state,
1754 struct dcerpc_do_request_state);
1761 state->object = object;
1762 state->opnum = opnum;
1763 state->request.blob = request;
1764 state->request.bigendian = bigendian;
1766 dcerpc_do_request_verification_trailer(req);
1767 if (!tevent_req_is_in_progress(req)) {
1768 return tevent_req_post(req, ev);
1771 state->call->incoming.private_data = req;
1772 state->call->incoming.handler = dcerpc_do_request_handle_in_frag;
1773 DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
1775 tevent_req_set_cleanup_fn(req, dcerpc_do_request_cleanup);
1776 tevent_req_defer_callback(req, ev);
1778 ok = tevent_queue_add(state->conn->calls.out_queue,
1781 dcerpc_do_request_out_frag_next,
1784 tevent_req_nomem(NULL, req);
1785 return tevent_req_post(req, ev);
1791 static void dcerpc_do_request_cleanup(struct tevent_req *req,
1792 enum tevent_req_state req_state)
1794 struct dcerpc_do_request_state *state =
1795 tevent_req_data(req,
1796 struct dcerpc_do_request_state);
1798 if (state->out_frag != NULL) {
1799 state->out_frag->req = NULL;
1800 state->out_frag = NULL;
1803 if (state->call != NULL) {
1804 if (state->call == state->conn->calls.active) {
1805 state->conn->calls.active = NULL;
1807 ZERO_STRUCT(state->call->incoming);
1808 DLIST_REMOVE(state->conn->calls.list, state->call);
1813 static void dcerpc_do_request_verification_trailer(struct tevent_req *req)
1815 struct dcerpc_do_request_state *state =
1816 tevent_req_data(req,
1817 struct dcerpc_do_request_state);
1818 struct dcerpc_sec_verification_trailer *t;
1819 struct dcerpc_sec_vt *c = NULL;
1820 struct ndr_push *ndr = NULL;
1821 enum ndr_err_code ndr_err;
1825 if (state->call->sec->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1829 t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1830 if (tevent_req_nomem(t, req)) {
1834 if (!state->call->sec->verified_bitmask1) {
1835 t->commands = talloc_realloc(t, t->commands,
1836 struct dcerpc_sec_vt,
1837 t->count.count + 1);
1838 if (tevent_req_nomem(t->commands, req)) {
1841 c = &t->commands[t->count.count++];
1844 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1845 if (state->call->sec->client_hdr_signing) {
1846 c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1848 state->verify_bitmask1 = true;
1851 if (!state->call->pres->verified_pcontext) {
1852 t->commands = talloc_realloc(t, t->commands,
1853 struct dcerpc_sec_vt,
1854 t->count.count + 1);
1855 if (tevent_req_nomem(t->commands, req)) {
1858 c = &t->commands[t->count.count++];
1861 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1862 c->u.pcontext.abstract_syntax = state->call->pres->table->syntax_id;
1863 c->u.pcontext.transfer_syntax = state->call->pres->transfer;
1865 state->verify_pcontext = true;
1868 if (!state->call->sec->hdr_signing) {
1869 t->commands = talloc_realloc(t, t->commands,
1870 struct dcerpc_sec_vt,
1871 t->count.count + 1);
1872 if (tevent_req_nomem(t->commands, req)) {
1875 c = &t->commands[t->count.count++];
1878 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1879 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1880 if (state->request.bigendian) {
1881 c->u.header2.drep[0] = 0;
1883 c->u.header2.drep[0] = DCERPC_DREP_LE;
1885 c->u.header2.drep[1] = 0;
1886 c->u.header2.drep[2] = 0;
1887 c->u.header2.drep[3] = 0;
1888 c->u.header2.call_id = state->call->call_id;
1889 c->u.header2.context_id = 0;
1890 c->u.header2.opnum = state->opnum;
1893 if (t->count.count == 0) {
1898 c = &t->commands[t->count.count - 1];
1899 c->command |= DCERPC_SEC_VT_COMMAND_END;
1901 if (DEBUGLEVEL >= 10) {
1902 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1905 ndr = ndr_push_init_ctx(state);
1906 if (tevent_req_nomem(ndr, req)) {
1910 //TODO if (state->request.bigendian)
1912 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1913 NDR_SCALARS | NDR_BUFFERS,
1915 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1916 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1917 tevent_req_nterror(req, status);
1920 state->request.trailer = ndr_push_blob(ndr);
1922 align = state->request.blob->length & 0x3;
1929 const uint8_t zeros[4] = { 0, };
1931 ok = data_blob_append(ndr, &state->request.trailer, zeros, pad);
1933 tevent_req_oom(req);
1937 /* move the padding to the start */
1938 p = state->request.trailer.data;
1939 memmove(p + pad, p, state->request.trailer.length - pad);
1946 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq);
1947 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq);
1948 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq);
1950 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
1953 struct dcerpc_do_request_state *state =
1954 tevent_req_data(req,
1955 struct dcerpc_do_request_state);
1956 struct dcerpc_do_request_out_frag *frag;
1957 size_t hdr_len = DCERPC_REQUEST_LENGTH;
1963 size_t data_thistime;
1964 size_t trailer_left;
1965 size_t trailer_thistime = 0;
1967 size_t total_thistime;
1969 union dcerpc_payload u;
1971 struct tevent_req *subreq;
1972 bool use_trans = true;
1974 if (state->object) {
1975 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1980 * the fragment belongs to the connection instead of the request
1981 * because it has to remain in case the request is canceled
1983 frag = talloc_zero(state->conn, struct dcerpc_do_request_out_frag);
1984 if (tevent_req_nomem(frag, req)) {
1987 frag->ev = state->ev;
1988 frag->conn = state->conn;
1990 state->out_frag = frag;
1992 data_left = state->request.blob->length - state->request.ofs;
1993 trailer_left = state->request.trailer.length - state->request.trailer_ofs;
1994 total_left = data_left + trailer_left;
1995 if (total_left < data_left || total_left < trailer_left) {
1996 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
2000 status = dcerpc_guess_pdu_sizes(state->call->sec,
2001 hdr_len, total_left,
2002 state->conn->features.max_xmit_frag,
2005 &frag_len, &auth_len, &pad_len);
2006 if (!NT_STATUS_IS_OK(status)) {
2007 tevent_req_nterror(req, status);
2011 if (state->request.ofs == 0) {
2012 flags |= DCERPC_PFC_FLAG_FIRST;
2015 if (total_thistime == total_left) {
2016 flags |= DCERPC_PFC_FLAG_LAST;
2019 data_thistime = MIN(total_thistime, data_left);
2020 if (data_thistime < total_thistime) {
2021 trailer_thistime = total_thistime - data_thistime;
2024 ZERO_STRUCT(u.request);
2026 u.request.alloc_hint = total_left;
2027 u.request.context_id = state->call->pres->context_id;
2028 u.request.opnum = state->opnum;
2029 if (state->object) {
2030 u.request.object.object = *state->object;
2032 //TODO pass state->request.bigendian
2033 status = dcerpc_ncacn_packet_blob(frag,
2037 state->call->call_id,
2040 if (!NT_STATUS_IS_OK(status)) {
2041 tevent_req_nterror(req, status);
2045 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2046 * compute it right for requests because the auth trailer is missing
2048 dcerpc_set_frag_length(&frag->blob, frag_len);
2050 if (data_thistime > 0) {
2051 const uint8_t *data_ptr;
2053 data_ptr = state->request.blob->data;
2054 data_ptr += state->request.ofs;
2056 /* Copy in the data. */
2057 ok = data_blob_append(frag, &frag->blob,
2058 data_ptr, data_thistime);
2060 tevent_req_oom(req);
2064 state->request.ofs += data_thistime;
2067 if (trailer_thistime > 0) {
2068 const uint8_t *trailer_ptr;
2070 trailer_ptr = state->request.trailer.data;
2071 trailer_ptr += state->request.trailer_ofs;
2073 /* Copy in the data. */
2074 ok = data_blob_append(frag, &frag->blob,
2075 trailer_ptr, trailer_thistime);
2077 tevent_req_oom(req);
2081 state->request.trailer_ofs += trailer_thistime;
2084 switch (state->call->sec->auth_level) {
2085 case DCERPC_AUTH_LEVEL_NONE:
2086 case DCERPC_AUTH_LEVEL_CONNECT:
2087 case DCERPC_AUTH_LEVEL_PACKET:
2089 case DCERPC_AUTH_LEVEL_INTEGRITY:
2090 case DCERPC_AUTH_LEVEL_PRIVACY:
2091 status = dcerpc_response_auth_blob(state->call->sec,
2094 if (!NT_STATUS_IS_OK(status)) {
2095 tevent_req_nterror(req, status);
2100 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2104 frag->is_last = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2106 if (!frag->is_last) {
2110 if (frag->conn->transport.use_trans_fn == NULL) {
2114 if (frag->conn->loop.subreq != NULL) {
2118 if (frag->conn->features.concurrent_multiplex) {
2122 if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
2127 frag->subreq_wait1 = tevent_queue_wait_send(frag,
2129 frag->conn->transport.write_queue);
2130 if (tevent_req_nomem(req, frag->subreq_wait1)) {
2133 tevent_req_set_callback(frag->subreq_wait1,
2134 dcerpc_do_request_out_frag_trans_wait1,
2137 * we need to block reads until our write is
2138 * the next in the write queue.
2140 frag->conn->loop.subreq = frag->subreq_wait1;
2141 frag->conn->loop.ev = frag->ev;
2145 * We need to add a dcerpc_write_fragment_queue_send/recv()
2148 frag->vector.iov_base = frag->blob.data;
2149 frag->vector.iov_len = frag->blob.length;
2150 subreq = tstream_writev_queue_send(frag, frag->ev,
2151 frag->conn->transport.stream,
2152 frag->conn->transport.write_queue,
2154 if (tevent_req_nomem(subreq, req)) {
2157 tevent_req_set_callback(subreq,
2158 dcerpc_do_request_out_frag_done,
2162 frag->subreq_wait2 = tevent_queue_wait_send(frag,
2164 frag->conn->transport.write_queue);
2165 if (tevent_req_nomem(req, frag->subreq_wait2)) {
2168 tevent_req_set_callback(frag->subreq_wait2,
2169 dcerpc_do_request_out_frag_trans_wait2,
2173 if (!frag->is_last) {
2177 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2178 if (tevent_req_nterror(req, status)) {
2183 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq)
2185 struct dcerpc_do_request_out_frag *frag =
2186 tevent_req_callback_data(subreq,
2187 struct dcerpc_do_request_out_frag);
2188 struct tevent_req *req = frag->req;
2193 * TODO; what if the caller has been free'ed?
2196 frag->subreq_wait1 = NULL;
2197 frag->conn->loop.subreq = NULL;
2199 ok = tevent_queue_wait_recv(subreq);
2201 status = NT_STATUS_INTERNAL_ERROR;
2204 tevent_req_nterror(req, status);
2206 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2210 if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
2212 * We added 3 entries into the queue,
2213 * wait1, writev and wait2.
2215 * There's more to write, we should not block
2216 * further writev calls for a trans call.
2218 * The wait2 stage will trigger the read.
2220 TALLOC_FREE(subreq);
2225 * we don't need wait2 anymore, we're sure that
2226 * we'll do a trans call.
2228 TALLOC_FREE(frag->subreq_wait2);
2230 status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
2231 if (!NT_STATUS_IS_OK(status)) {
2234 tevent_req_nterror(req, status);
2236 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2240 /* we free subreq after tstream_cli_np_use_trans */
2241 TALLOC_FREE(subreq);
2243 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2244 if (!NT_STATUS_IS_OK(status)) {
2247 tevent_req_nterror(req, status);
2249 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2254 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq)
2256 struct dcerpc_do_request_out_frag *frag =
2257 tevent_req_callback_data(subreq,
2258 struct dcerpc_do_request_out_frag);
2259 struct tevent_req *req = frag->req;
2265 * If the caller has been free'ed, we have should
2266 * ignore any errors and just free 'frag'
2269 struct dcerpc_do_request_state *state =
2270 tevent_req_data(req,
2271 struct dcerpc_do_request_state);
2273 state->out_frag = NULL;
2276 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2277 TALLOC_FREE(subreq);
2280 status = map_nt_error_from_unix_common(sys_errno);
2282 tevent_req_nterror(req, status);
2287 if (frag->subreq_wait2 != NULL) {
2291 if (frag->is_last) {
2301 dcerpc_do_request_out_frag_next(req, NULL);
2304 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq)
2306 struct dcerpc_do_request_out_frag *frag =
2307 tevent_req_callback_data(subreq,
2308 struct dcerpc_do_request_out_frag);
2309 struct tevent_req *req = frag->req;
2313 frag->subreq_wait2 = NULL;
2315 ok = tevent_queue_wait_recv(subreq);
2317 status = NT_STATUS_INTERNAL_ERROR;
2320 tevent_req_nterror(req, status);
2322 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2326 TALLOC_FREE(subreq);
2328 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2329 if (!NT_STATUS_IS_OK(status)) {
2332 tevent_req_nterror(req, status);
2334 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2340 /* we need to wait for incoming pdus */
2343 static NTSTATUS dcerpc_do_request_handle_in_frag(void *private_data,
2344 struct ncacn_packet *pkt,
2347 struct tevent_req *req =
2348 talloc_get_type_abort(private_data,
2350 struct dcerpc_do_request_state *state =
2351 tevent_req_data(req,
2352 struct dcerpc_do_request_state);
2361 /* Ensure we have the correct type. */
2362 switch (pkt->ptype) {
2363 case DCERPC_PKT_RESPONSE:
2365 /* Here's where we deal with incoming sign/seal. */
2366 error = dcerpc_check_pdu_auth(state->call->sec,
2368 &pkt->u.response.stub_and_verifier,
2369 DCERPC_RESPONSE_LENGTH,
2371 if (!NT_STATUS_IS_OK(error)) {
2375 if (!state->got_first) {
2376 state->got_first = true;
2378 if (pkt->drep[0] & DCERPC_DREP_LE) {
2379 state->response.bigendian = false;
2381 state->response.bigendian = true;
2384 if (state->verify_bitmask1) {
2385 state->call->sec->verified_bitmask1 = true;
2388 if (state->verify_pcontext) {
2389 state->call->pres->verified_pcontext = true;
2393 if (state->response.bigendian) {
2394 if (pkt->drep[0] != 0) {
2395 return NT_STATUS_RPC_PROTOCOL_ERROR;
2398 if (pkt->drep[0] != DCERPC_DREP_LE) {
2399 return NT_STATUS_RPC_PROTOCOL_ERROR;
2402 if (pkt->drep[1] != 0) {
2403 return NT_STATUS_RPC_PROTOCOL_ERROR;
2405 if (pkt->drep[2] != 0) {
2406 return NT_STATUS_RPC_PROTOCOL_ERROR;
2408 if (pkt->drep[3] != 0) {
2409 return NT_STATUS_RPC_PROTOCOL_ERROR;
2412 if (pkt->u.response.context_id != state->call->pres->context_id) {
2413 return NT_STATUS_RPC_PROTOCOL_ERROR;
2416 if (frag.length < DCERPC_RESPONSE_LENGTH + pad_len) {
2417 return NT_STATUS_RPC_PROTOCOL_ERROR;
2420 /* Point the return values at the NDR data. */
2421 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
2423 if (pkt->auth_length) {
2424 /* We've already done integer wrap tests in
2425 * dcerpc_check_auth(). */
2426 payload.length = frag.length
2427 - DCERPC_RESPONSE_LENGTH
2429 - DCERPC_AUTH_TRAILER_LENGTH
2432 payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
2435 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
2436 (long unsigned int)frag.length,
2437 (long unsigned int)payload.length,
2438 (unsigned int)pad_len));
2441 * If this is the first reply, and the allocation hint is
2442 * reasonable, try and set up the reply_pdu DATA_BLOB to the
2446 if ((state->response.blob.length == 0) &&
2447 pkt->u.response.alloc_hint &&
2448 (pkt->u.response.alloc_hint < 15*1024*1024)) {
2449 ok = data_blob_realloc(state, &state->response.blob,
2450 pkt->u.response.alloc_hint);
2452 DEBUG(0, ("reply alloc hint %d too "
2453 "large to allocate\n",
2454 (int)pkt->u.response.alloc_hint));
2455 return NT_STATUS_NO_MEMORY;
2459 new_total = state->response.ofs + payload.length;
2461 if (new_total > 15 * 1024 *1024) {
2462 return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
2465 missing = new_total - state->response.blob.length;
2468 ok = data_blob_realloc(state, &state->response.blob,
2471 DEBUG(0, ("reply alloc hint %d too "
2472 "large to allocate\n",
2473 (int)pkt->u.response.alloc_hint));
2474 return NT_STATUS_NO_MEMORY;
2478 memcpy(state->response.blob.data + state->response.ofs,
2479 payload.data, payload.length);
2480 state->response.ofs += payload.length;
2482 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
2483 tevent_req_done(req);//TODO
2484 return NT_STATUS_OK;
2487 return dcerpc_connection_loop_restart(state->conn, state->ev);
2489 case DCERPC_PKT_FAULT:
2491 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
2492 "code %s received from %s!\n",
2493 dcerpc_errstr(talloc_tos(),
2494 pkt->u.fault.status),
2497 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
2498 if (NT_STATUS_IS_OK(status)) {
2499 status = NT_STATUS_RPC_PROTOCOL_ERROR;
2502 tevent_req_nterror(req, status);//TODO
2503 return NT_STATUS_OK;
2505 DEBUG(0, ("Unknown packet type %u received from %s!\n",
2506 (unsigned int)pkt->ptype,
2508 return NT_STATUS_RPC_PROTOCOL_ERROR;
2512 NTSTATUS dcerpc_do_request_recv(struct tevent_req *req,
2513 TALLOC_CTX *mem_ctx,
2514 DATA_BLOB *response,
2517 struct dcerpc_do_request_state *state =
2518 tevent_req_data(req,
2519 struct dcerpc_do_request_state);
2522 if (tevent_req_is_nterror(req, &status)) {
2523 tevent_req_received(req);
2527 /* return data to caller and assign it ownership of memory */
2528 response->data = talloc_move(mem_ctx, &state->response.blob.data);
2529 response->length = state->response.blob.length;
2530 *bigendian = state->response.bigendian;
2532 tevent_req_received(req);
2533 return NT_STATUS_OK;