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;
700 conn->loop.subreq = NULL;
702 error = dcerpc_read_ncacn_packet_recv(subreq, subreq, &pkt, &pdu);
703 if (!NT_STATUS_IS_OK(error)) {
705 // disconnect and notify pending calls
709 if (DEBUGLEVEL >= 10) {
710 NDR_PRINT_DEBUG(ncacn_packet, pkt);
713 switch (pkt->ptype) {
714 case DCERPC_PKT_REQUEST:
715 /* Ordinary request. */
719 case DCERPC_PKT_PING:
720 /* Connectionless is server alive ? */
723 case DCERPC_PKT_RESPONSE:
724 /* Ordinary reply. */
728 case DCERPC_PKT_FAULT:
729 /* Fault in processing of call. */
733 case DCERPC_PKT_WORKING:
734 /* Connectionless reply to a ping when server busy. */
737 case DCERPC_PKT_NOCALL:
738 /* Connectionless reply to a ping when server has lost part of clients call. */
741 case DCERPC_PKT_REJECT:
742 /* Refuse a request with a code. */
748 case DCERPC_PKT_CL_CANCEL:
751 case DCERPC_PKT_FACK:
754 case DCERPC_PKT_CANCEL_ACK:
755 /* Server ACK to client cancel request. */
758 case DCERPC_PKT_BIND:
759 /* Bind to interface. */
763 case DCERPC_PKT_BIND_ACK:
764 /* Server ack of bind. */
768 case DCERPC_PKT_BIND_NAK:
769 /* Server nack of bind. */
773 case DCERPC_PKT_ALTER:
778 case DCERPC_PKT_ALTER_RESP:
779 /* Reply to alter auth. */
783 case DCERPC_PKT_AUTH3:
784 /* not the real name! this is undocumented! */
788 case DCERPC_PKT_SHUTDOWN:
789 /* Server to client request to shutdown. */
793 case DCERPC_PKT_CO_CANCEL:
794 /* Connection-oriented cancel request. */
798 case DCERPC_PKT_ORPHANED:
799 /* Client telling server it's aborting a partially sent request or telling server to stop sending replies. */
804 /* RTS packets used in ncacn_http */
810 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
814 if (conn->calls.active != NULL) {
815 if (pkt->call_id != conn->calls.active->call_id) {
817 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
820 call = conn->calls.active;
822 call = conn->calls.list;
825 for (call = conn->calls.list; call; call = call->next) {
826 if (call->call_id == pkt->call_id) {
832 call = conn->calls.new_call;
837 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
841 if (call->incoming.handler == NULL) {
843 // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
847 error = call->incoming.handler(call->incoming.private_data, pkt, pdu);
849 if (!NT_STATUS_IS_OK(error)) {
850 // disconnect and notify pending calls
854 if (conn->calls.new_call == NULL) {
855 conn->loop.ev = NULL;
859 error = dcerpc_connection_loop_restart(conn, conn->loop.ev);
860 if (!NT_STATUS_IS_OK(error)) {
861 // disconnect and notify pending calls
866 struct dcerpc_do_bind_out_frag;
868 struct dcerpc_do_bind_state {
869 struct tevent_context *ev;
870 struct dcerpc_connection *conn;
871 struct dcerpc_call *call;
872 struct dcerpc_security *sec;
873 bool proposed_hdr_signing;
877 struct dcerpc_do_bind_out_frag *out_frag;
879 struct dcerpc_presentation **pres;
880 uint32_t remaining_pres;
883 struct dcerpc_ctx_list *ctx_list;
884 struct ndr_syntax_id features;
887 struct dcerpc_do_bind_out_frag {
888 struct tevent_context *ev;
889 struct dcerpc_connection *conn;
890 struct tevent_req *req;
891 enum dcerpc_pkt_type ptype;
894 struct tevent_req *subreq_wait1;
895 struct tevent_req *subreq_wait2;
898 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
899 enum tevent_req_state req_state);
901 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq);
902 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq);
904 static NTSTATUS dcerpc_do_bind_handle_in_frag(void *private_data,
905 struct ncacn_packet *pkt,
908 struct tevent_req *dcerpc_do_bind_send(TALLOC_CTX *mem_ctx,
909 struct tevent_context *ev,
910 struct dcerpc_connection *conn,
911 struct dcerpc_call *call,
912 struct dcerpc_security *sec,
914 struct dcerpc_presentation **pres)
916 struct tevent_req *req;
917 struct dcerpc_do_bind_state *state;
918 struct tevent_req *subreq;
920 req = tevent_req_create(mem_ctx, &state,
921 struct dcerpc_do_bind_state);
929 state->num_pres = num_pres;
932 state->call->incoming.private_data = req;
933 state->call->incoming.handler = dcerpc_do_bind_handle_in_frag;
934 DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
936 tevent_req_set_cleanup_fn(req, dcerpc_do_bind_cleanup);
937 tevent_req_defer_callback(req, ev);
939 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
940 subreq = gensec_update_send(state, ev,
943 if (tevent_req_nomem(subreq, req)) {
944 return tevent_req_post(req, ev);
946 tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
951 state->sec_status = NT_STATUS_OK;
953 subreq = tevent_queue_wait_send(state, state->ev,
954 state->conn->calls.out_queue);
955 if (tevent_req_nomem(subreq, req)) {
956 return tevent_req_post(req, ev);
958 tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
963 static void dcerpc_do_bind_cleanup(struct tevent_req *req,
964 enum tevent_req_state req_state)
966 struct dcerpc_do_bind_state *state =
968 struct dcerpc_do_bind_state);
970 if (state->out_frag != NULL) {
971 state->out_frag->req = NULL;
972 state->out_frag = NULL;
975 if (state->call != NULL) {
976 ZERO_STRUCT(state->call->incoming);
977 DLIST_REMOVE(state->conn->calls.list, state->call);
982 static void dcerpc_do_bind_sec_next(struct tevent_req *subreq)
984 struct tevent_req *req =
985 tevent_req_callback_data(subreq,
987 struct dcerpc_do_bind_state *state =
989 struct dcerpc_do_bind_state);
992 data_blob_free(&state->sec_out);
993 status = gensec_update_recv(subreq, state, &state->sec_out);
995 data_blob_free(&state->sec_in);
996 state->sec_status = status;
997 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
998 status = NT_STATUS_OK;
1000 if (!NT_STATUS_IS_OK(status)) {
1001 tevent_req_nterror(req, status);
1005 if (NT_STATUS_IS_OK(state->sec_status) &&
1006 state->sec_out.length == 0)
1008 tevent_req_done(req);
1012 if (state->sec->auth_level >= DCERPC_AUTH_LEVEL_INTEGRITY) {
1013 state->sec->client_hdr_signing =
1014 gensec_have_feature(state->sec->gensec,
1015 GENSEC_FEATURE_SIGN_PKT_HEADER);
1018 subreq = tevent_queue_wait_send(state, state->ev,
1019 state->conn->calls.out_queue);
1020 if (tevent_req_nomem(subreq, req)) {
1023 tevent_req_set_callback(subreq, dcerpc_do_bind_out_frag_next, req);
1026 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq);
1027 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq);
1028 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq);
1030 static void dcerpc_do_bind_out_frag_next(struct tevent_req *subreq)
1032 struct tevent_req *req =
1033 tevent_req_callback_data(subreq,
1035 struct dcerpc_do_bind_state *state =
1036 tevent_req_data(req,
1037 struct dcerpc_do_bind_state);
1038 struct dcerpc_do_bind_out_frag *frag;
1039 size_t auth_len = 0;
1041 DATA_BLOB auth_info = data_blob_null;
1042 uint8_t pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
1043 union dcerpc_payload u;
1045 bool require_ack = false;
1046 bool use_trans = true;
1049 ok = tevent_queue_wait_recv(subreq);
1051 //status = NT_STATUS_INTERNAL_ERROR;
1052 tevent_req_oom(req);
1055 TALLOC_FREE(subreq);
1058 * the fragment belongs to the connection instead of the request
1059 * because it has to remain in case the request is canceled
1061 frag = talloc_zero(state->conn, struct dcerpc_do_bind_out_frag);
1062 if (tevent_req_nomem(frag, req)) {
1065 frag->ev = state->ev;
1066 frag->conn = state->conn;
1068 state->out_frag = frag;
1070 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1071 if (state->sec->client_hdr_signing &&
1072 !state->proposed_hdr_signing)
1074 state->proposed_hdr_signing = true;
1075 pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
1080 //TODO : DCERPC_PFC_FLAG_CONC_MPX
1082 //TODO: remaining_pres
1084 if (!state->conn->features.bind_done) {
1085 frag->ptype = DCERPC_PKT_BIND;
1086 } else if (require_ack) {
1087 frag->ptype = DCERPC_PKT_ALTER;
1088 } else if (state->remaining_pres > 0) {
1089 frag->ptype = DCERPC_PKT_ALTER;
1090 } else if (!NT_STATUS_IS_OK(state->sec_status)) {
1091 frag->ptype = DCERPC_PKT_ALTER;
1093 frag->ptype = DCERPC_PKT_AUTH3;
1096 if (state->sec && state->sec->auth_type != DCERPC_AUTH_TYPE_NONE) {
1097 status = dcerpc_auth_blob(frag,
1098 state->sec->auth_type,
1099 state->sec->auth_level,
1100 0, /* auth_pad_length */
1101 state->sec->context_id, /* auth_context_id */
1104 if (!NT_STATUS_IS_OK(status)) {
1105 tevent_req_nterror(req, status);
1109 auth_len = auth_info.length;
1112 auth_len -= DCERPC_AUTH_TRAILER_LENGTH;
1116 state->num_ctx = state->num_pres;
1117 if (!state->conn->assoc->negotiate_done) {
1118 state->num_ctx += 1;
1121 state->ctx_list = talloc_zero_array(frag,
1122 struct dcerpc_ctx_list,
1124 if (tevent_req_nomem(state->ctx_list, req)) {
1128 for (i=0; i < state->num_pres; i++) {
1129 state->ctx_list[i] = state->pres[i]->negotiate.req;
1132 if (!state->conn->assoc->negotiate_done) {
1133 state->features = dcerpc_construct_bind_time_features(
1134 state->conn->assoc->client_features);
1136 state->ctx_list[i].context_id = state->conn->next_pres_context_id;
1138 state->ctx_list[i].abstract_syntax =
1139 state->ctx_list[i-1].abstract_syntax;
1141 state->ctx_list[i].num_transfer_syntaxes = 1;
1142 state->ctx_list[i].transfer_syntaxes = &state->features;
1145 switch (frag->ptype) {
1146 case DCERPC_PKT_BIND:
1147 case DCERPC_PKT_ALTER:
1148 u.bind.max_xmit_frag = state->conn->features.max_xmit_frag;
1149 u.bind.max_recv_frag = state->conn->features.max_recv_frag;
1150 u.bind.assoc_group_id = state->conn->assoc->assoc_group_id;
1151 u.bind.num_contexts = state->num_ctx;
1152 u.bind.ctx_list = state->ctx_list;
1153 u.bind.auth_info = auth_info;
1156 case DCERPC_PKT_AUTH3:
1158 u.auth3.auth_info = auth_info;
1161 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1165 status = dcerpc_ncacn_packet_blob(frag,
1169 state->call->call_id,
1172 if (!NT_STATUS_IS_OK(status)) {
1173 DEBUG(0, ("Failed to marshall bind/alter ncacn_packet.\n"));
1174 tevent_req_nterror(req, status);
1178 if (frag->ptype == DCERPC_PKT_AUTH3) {
1182 if (frag->conn->transport.use_trans_fn == NULL) {
1186 if (frag->conn->loop.subreq != NULL) {
1190 if (frag->conn->features.concurrent_multiplex) {
1194 if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
1199 frag->subreq_wait1 = tevent_queue_wait_send(frag,
1201 frag->conn->transport.write_queue);
1202 if (tevent_req_nomem(req, frag->subreq_wait1)) {
1205 tevent_req_set_callback(frag->subreq_wait1,
1206 dcerpc_do_bind_out_frag_trans_wait1,
1209 * we need to block reads until our write is
1210 * the next in the write queue.
1212 frag->conn->loop.subreq = frag->subreq_wait1;
1213 frag->conn->loop.ev = frag->ev;
1217 * We need to add a dcerpc_write_fragment_queue_send/recv()
1220 frag->vector.iov_base = frag->blob.data;
1221 frag->vector.iov_len = frag->blob.length;
1222 subreq = tstream_writev_queue_send(frag, frag->ev,
1223 frag->conn->transport.stream,
1224 frag->conn->transport.write_queue,
1226 if (tevent_req_nomem(subreq, req)) {
1229 tevent_req_set_callback(subreq,
1230 dcerpc_do_bind_out_frag_done,
1234 frag->subreq_wait2 = tevent_queue_wait_send(frag,
1236 frag->conn->transport.write_queue);
1237 if (tevent_req_nomem(req, frag->subreq_wait2)) {
1240 tevent_req_set_callback(frag->subreq_wait2,
1241 dcerpc_do_bind_out_frag_trans_wait2,
1245 if (frag->ptype == DCERPC_PKT_AUTH3) {
1249 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1250 if (tevent_req_nterror(req, status)) {
1255 static void dcerpc_do_bind_out_frag_trans_wait1(struct tevent_req *subreq)
1257 struct dcerpc_do_bind_out_frag *frag =
1258 tevent_req_callback_data(subreq,
1259 struct dcerpc_do_bind_out_frag);
1260 struct tevent_req *req = frag->req;
1265 * TODO; what if the caller has been free'ed?
1268 frag->subreq_wait1 = NULL;
1269 frag->conn->loop.subreq = NULL;
1271 ok = tevent_queue_wait_recv(subreq);
1273 status = NT_STATUS_INTERNAL_ERROR;
1276 tevent_req_nterror(req, status);
1278 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1282 if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
1284 * We added 3 entries into the queue,
1285 * wait1, writev and wait2.
1287 * There's more to write, we should not block
1288 * further writev calls for a trans call.
1290 * The wait2 stage will trigger the read.
1292 TALLOC_FREE(subreq);
1297 * we don't need wait2 anymore, we're sure that
1298 * we'll do a trans call.
1300 TALLOC_FREE(frag->subreq_wait2);
1302 status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
1303 if (!NT_STATUS_IS_OK(status)) {
1306 tevent_req_nterror(req, status);
1308 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1312 /* we free subreq after tstream_cli_np_use_trans */
1313 TALLOC_FREE(subreq);
1315 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1316 if (!NT_STATUS_IS_OK(status)) {
1319 tevent_req_nterror(req, status);
1321 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1326 static void dcerpc_do_bind_out_frag_done(struct tevent_req *subreq)
1328 struct dcerpc_do_bind_out_frag *frag =
1329 tevent_req_callback_data(subreq,
1330 struct dcerpc_do_bind_out_frag);
1331 struct tevent_req *req = frag->req;
1337 * If the caller has been free'ed, we have should
1338 * ignore any errors and just free 'frag'
1341 struct dcerpc_do_bind_state *state =
1342 tevent_req_data(req,
1343 struct dcerpc_do_bind_state);
1345 state->out_frag = NULL;
1348 ret = tstream_writev_queue_recv(subreq, &sys_errno);
1349 TALLOC_FREE(subreq);
1352 status = map_nt_error_from_unix_common(sys_errno);
1354 tevent_req_nterror(req, status);
1359 if (frag->ptype == DCERPC_PKT_AUTH3) {
1364 tevent_req_done(req);
1368 if (frag->subreq_wait2 != NULL) {
1374 /* we need to wait for incoming pdus */
1377 static void dcerpc_do_bind_out_frag_trans_wait2(struct tevent_req *subreq)
1379 struct dcerpc_do_bind_out_frag *frag =
1380 tevent_req_callback_data(subreq,
1381 struct dcerpc_do_bind_out_frag);
1382 struct tevent_req *req = frag->req;
1386 frag->subreq_wait2 = NULL;
1388 ok = tevent_queue_wait_recv(subreq);
1390 status = NT_STATUS_INTERNAL_ERROR;
1393 tevent_req_nterror(req, status);
1395 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1399 TALLOC_FREE(subreq);
1401 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
1402 if (!NT_STATUS_IS_OK(status)) {
1405 tevent_req_nterror(req, status);
1407 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
1413 /* we need to wait for incoming pdus */
1416 static NTSTATUS dcerpc_do_bind_handle_in_frag(void *private_data,
1417 struct ncacn_packet *pkt,
1420 struct tevent_req *req =
1421 talloc_get_type_abort(private_data,
1423 struct dcerpc_do_bind_state *state =
1424 tevent_req_data(req,
1425 struct dcerpc_do_bind_state);
1429 /* Ensure we have the correct type. */
1430 switch (pkt->ptype) {
1431 case DCERPC_PKT_BIND_ACK:
1432 case DCERPC_PKT_ALTER_RESP:
1433 if (!state->conn->features.bind_done) {
1434 if (pkt->u.bind_ack.max_recv_frag < 1234) {
1435 return NT_STATUS_RPC_PROTOCOL_ERROR;
1437 if (pkt->u.bind_ack.max_xmit_frag < 1234) {
1438 return NT_STATUS_RPC_PROTOCOL_ERROR;
1440 state->conn->features.max_recv_frag =
1441 pkt->u.bind_ack.max_recv_frag;
1442 state->conn->features.max_xmit_frag =
1443 pkt->u.bind_ack.max_xmit_frag;
1445 if (pkt->pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) {
1446 state->conn->features.concurrent_multiplex = true;
1449 state->conn->features.bind_done = true;
1452 if (!state->conn->assoc->negotiate_done) {
1453 state->conn->assoc->negotiate_done = true;
1454 state->conn->assoc->assoc_group_id = pkt->u.bind_ack.assoc_group_id;
1457 if (pkt->u.bind_ack.assoc_group_id != state->conn->assoc->assoc_group_id) {
1458 return NT_STATUS_RPC_PROTOCOL_ERROR;
1461 if (pkt->u.bind_ack.num_results > state->num_ctx) {
1462 return NT_STATUS_RPC_PROTOCOL_ERROR;
1465 if (state->proposed_hdr_signing) {
1466 if (pkt->pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
1467 state->sec->hdr_signing = true;
1471 for (i = 0; i < pkt->u.bind_ack.num_results; i++) {
1472 struct dcerpc_ack_ctx *ack = &pkt->u.bind_ack.ctx_list[i];
1474 if (i < state->num_pres) {
1475 state->pres[i]->negotiate.ack = *ack;
1479 if (ack->result != DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
1483 state->conn->assoc->features = state->conn->assoc->client_features;
1484 state->conn->assoc->features &= ack->reason.negotiate;
1487 for (i = 0; i < state->num_pres; i++) {
1488 struct dcerpc_ack_ctx *ack = &state->pres[i]->negotiate.ack;
1491 if (ack->result != DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
1495 ok = ndr_syntax_id_equal(&state->pres[i]->transfer,
1498 return NT_STATUS_RPC_PROTOCOL_ERROR;
1502 if (pkt->auth_length >= 8) {
1503 struct tevent_req *subreq;
1505 state->sec_in = data_blob_talloc(state,
1506 pkt->u.bind_ack.auth_info.data + 8,
1507 pkt->u.bind_ack.auth_info.length - 8);
1509 subreq = gensec_update_send(state, state->ev,
1512 if (tevent_req_nomem(subreq, req)) {
1513 return NT_STATUS_OK;
1515 tevent_req_set_callback(subreq, dcerpc_do_bind_sec_next, req);
1516 return NT_STATUS_OK;
1519 tevent_req_done(req);
1520 return NT_STATUS_OK;
1522 //case DCERPC_PKT_ALTER_RESP:
1523 if (pkt->auth_length != 0) {
1524 return NT_STATUS_NOT_IMPLEMENTED;
1527 return NT_STATUS_NOT_IMPLEMENTED;
1530 /* Point the return values at the NDR data. */
1531 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
1533 if (pkt->auth_length) {
1534 /* We've already done integer wrap tests in
1535 * dcerpc_check_auth(). */
1536 payload.length = frag.length
1537 - DCERPC_RESPONSE_LENGTH
1539 - DCERPC_AUTH_TRAILER_LENGTH
1542 payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
1545 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1546 if (pkt->drep[0] & DCERPC_DREP_LE) {
1547 state->response.bigendian = false;
1549 state->response.bigendian = true;
1553 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
1554 (long unsigned int)frag.length,
1555 (long unsigned int)payload.length,
1556 (unsigned int)pad_len));
1559 * If this is the first reply, and the allocation hint is
1560 * reasonable, try and set up the reply_pdu DATA_BLOB to the
1564 if ((state->response.blob.length == 0) &&
1565 pkt->u.response.alloc_hint &&
1566 (pkt->u.response.alloc_hint < 15*1024*1024)) {
1567 ok = data_blob_realloc(state, &state->response.blob,
1568 pkt->u.response.alloc_hint);
1570 DEBUG(0, ("reply alloc hint %d too "
1571 "large to allocate\n",
1572 (int)pkt->u.response.alloc_hint));
1573 return NT_STATUS_NO_MEMORY;
1577 new_total = state->response.ofs + payload.length;
1579 if (new_total > 15 * 1024 *1024) {
1580 return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
1583 missing = new_total - state->response.blob.length;
1586 ok = data_blob_realloc(state, &state->response.blob,
1589 DEBUG(0, ("reply alloc hint %d too "
1590 "large to allocate\n",
1591 (int)pkt->u.response.alloc_hint));
1592 return NT_STATUS_NO_MEMORY;
1596 memcpy(state->response.blob.data + state->response.ofs,
1597 payload.data, payload.length);
1598 state->response.ofs += payload.length;
1600 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
1601 tevent_req_done(req);//TODO
1602 return NT_STATUS_OK;
1604 return NT_STATUS_OK;
1606 return NT_STATUS_NOT_IMPLEMENTED;
1608 case DCERPC_PKT_FAULT:
1610 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
1611 "code %s received from %s!\n",
1612 dcerpc_errstr(talloc_tos(),
1613 pkt->u.fault.status),
1616 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
1617 if (NT_STATUS_IS_OK(status)) {
1618 status = NT_STATUS_RPC_PROTOCOL_ERROR;
1621 tevent_req_nterror(req, status);//TODO
1622 return NT_STATUS_OK;
1624 DEBUG(0, ("Unknown packet type %u received from %s!\n",
1625 (unsigned int)pkt->ptype,
1627 return NT_STATUS_RPC_PROTOCOL_ERROR;
1630 return NT_STATUS_RPC_PROTOCOL_ERROR;
1633 NTSTATUS dcerpc_do_bind_recv(struct tevent_req *req)
1635 struct dcerpc_do_bind_state *state =
1636 tevent_req_data(req,
1637 struct dcerpc_do_bind_state);
1640 if (tevent_req_is_nterror(req, &status)) {
1641 tevent_req_received(req);
1645 if (!NT_STATUS_IS_OK(state->sec_status)) {
1646 status = state->sec_status;
1647 tevent_req_received(req);
1651 tevent_req_received(req);
1652 return NT_STATUS_OK;
1655 struct dcerpc_do_request_out_frag;
1657 struct dcerpc_do_request_state {
1658 struct tevent_context *ev;
1659 struct dcerpc_connection *conn;
1660 struct dcerpc_call *call;
1661 const struct GUID *object;
1664 const DATA_BLOB *blob;
1670 bool verify_bitmask1;
1671 bool verify_pcontext;
1673 struct dcerpc_do_request_out_frag *out_frag;
1681 struct dcerpc_do_request_out_frag {
1682 struct tevent_context *ev;
1683 struct dcerpc_connection *conn;
1684 struct tevent_req *req;
1687 struct iovec vector;
1688 struct tevent_req *subreq_wait1;
1689 struct tevent_req *subreq_wait2;
1692 static void dcerpc_do_request_cleanup(struct tevent_req *req,
1693 enum tevent_req_state req_state);
1695 static void dcerpc_do_request_verification_trailer(struct tevent_req *req);
1696 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
1697 void *private_data);
1699 static NTSTATUS dcerpc_do_request_handle_in_frag(void *private_data,
1700 struct ncacn_packet *pkt,
1703 struct tevent_req *dcerpc_do_request_send(TALLOC_CTX *mem_ctx,
1704 struct tevent_context *ev,
1705 struct dcerpc_connection *conn,
1706 struct dcerpc_call *call,
1707 const struct GUID *object,
1709 const DATA_BLOB *request,
1712 struct tevent_req *req;
1713 struct dcerpc_do_request_state *state;
1716 req = tevent_req_create(mem_ctx, &state,
1717 struct dcerpc_do_request_state);
1724 state->object = object;
1725 state->opnum = opnum;
1726 state->request.blob = request;
1727 state->request.bigendian = bigendian;
1729 dcerpc_do_request_verification_trailer(req);
1730 if (!tevent_req_is_in_progress(req)) {
1731 return tevent_req_post(req, ev);
1734 state->call->incoming.private_data = req;
1735 state->call->incoming.handler = dcerpc_do_request_handle_in_frag;
1736 DLIST_ADD_END(state->conn->calls.list, state->call, NULL);
1738 tevent_req_set_cleanup_fn(req, dcerpc_do_request_cleanup);
1739 tevent_req_defer_callback(req, ev);
1741 ok = tevent_queue_add(state->conn->calls.out_queue,
1744 dcerpc_do_request_out_frag_next,
1747 tevent_req_nomem(NULL, req);
1748 return tevent_req_post(req, ev);
1754 static void dcerpc_do_request_cleanup(struct tevent_req *req,
1755 enum tevent_req_state req_state)
1757 struct dcerpc_do_request_state *state =
1758 tevent_req_data(req,
1759 struct dcerpc_do_request_state);
1761 if (state->out_frag != NULL) {
1762 state->out_frag->req = NULL;
1763 state->out_frag = NULL;
1766 if (state->call != NULL) {
1767 if (state->call == state->conn->calls.active) {
1768 state->conn->calls.active = NULL;
1770 ZERO_STRUCT(state->call->incoming);
1771 DLIST_REMOVE(state->conn->calls.list, state->call);
1776 static void dcerpc_do_request_verification_trailer(struct tevent_req *req)
1778 struct dcerpc_do_request_state *state =
1779 tevent_req_data(req,
1780 struct dcerpc_do_request_state);
1781 struct dcerpc_sec_verification_trailer *t;
1782 struct dcerpc_sec_vt *c = NULL;
1783 struct ndr_push *ndr = NULL;
1784 enum ndr_err_code ndr_err;
1788 if (state->call->sec->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1792 t = talloc_zero(state, struct dcerpc_sec_verification_trailer);
1793 if (tevent_req_nomem(t, req)) {
1797 if (!state->call->sec->verified_bitmask1) {
1798 t->commands = talloc_realloc(t, t->commands,
1799 struct dcerpc_sec_vt,
1800 t->count.count + 1);
1801 if (tevent_req_nomem(t->commands, req)) {
1804 c = &t->commands[t->count.count++];
1807 c->command = DCERPC_SEC_VT_COMMAND_BITMASK1;
1808 if (state->call->sec->client_hdr_signing) {
1809 c->u.bitmask1 = DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING;
1811 state->verify_bitmask1 = true;
1814 if (!state->call->pres->verified_pcontext) {
1815 t->commands = talloc_realloc(t, t->commands,
1816 struct dcerpc_sec_vt,
1817 t->count.count + 1);
1818 if (tevent_req_nomem(t->commands, req)) {
1821 c = &t->commands[t->count.count++];
1824 c->command = DCERPC_SEC_VT_COMMAND_PCONTEXT;
1825 c->u.pcontext.abstract_syntax = state->call->pres->table->syntax_id;
1826 c->u.pcontext.transfer_syntax = state->call->pres->transfer;
1828 state->verify_pcontext = true;
1831 if (!state->call->sec->hdr_signing) {
1832 t->commands = talloc_realloc(t, t->commands,
1833 struct dcerpc_sec_vt,
1834 t->count.count + 1);
1835 if (tevent_req_nomem(t->commands, req)) {
1838 c = &t->commands[t->count.count++];
1841 c->command = DCERPC_SEC_VT_COMMAND_HEADER2;
1842 c->u.header2.ptype = DCERPC_PKT_REQUEST;
1843 if (state->request.bigendian) {
1844 c->u.header2.drep[0] = 0;
1846 c->u.header2.drep[0] = DCERPC_DREP_LE;
1848 c->u.header2.drep[1] = 0;
1849 c->u.header2.drep[2] = 0;
1850 c->u.header2.drep[3] = 0;
1851 c->u.header2.call_id = state->call->call_id;
1852 c->u.header2.context_id = 0;
1853 c->u.header2.opnum = state->opnum;
1856 if (t->count.count == 0) {
1861 c = &t->commands[t->count.count - 1];
1862 c->command |= DCERPC_SEC_VT_COMMAND_END;
1864 if (DEBUGLEVEL >= 10) {
1865 NDR_PRINT_DEBUG(dcerpc_sec_verification_trailer, t);
1868 ndr = ndr_push_init_ctx(state);
1869 if (tevent_req_nomem(ndr, req)) {
1873 //TODO if (state->request.bigendian)
1875 ndr_err = ndr_push_dcerpc_sec_verification_trailer(ndr,
1876 NDR_SCALARS | NDR_BUFFERS,
1878 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1879 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1880 tevent_req_nterror(req, status);
1883 state->request.trailer = ndr_push_blob(ndr);
1885 align = state->request.blob->length & 0x3;
1892 const uint8_t zeros[4] = { 0, };
1894 ok = data_blob_append(ndr, &state->request.trailer, zeros, pad);
1896 tevent_req_oom(req);
1900 /* move the padding to the start */
1901 p = state->request.trailer.data;
1902 memmove(p + pad, p, state->request.trailer.length - pad);
1909 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq);
1910 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq);
1911 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq);
1913 static void dcerpc_do_request_out_frag_next(struct tevent_req *req,
1916 struct dcerpc_do_request_state *state =
1917 tevent_req_data(req,
1918 struct dcerpc_do_request_state);
1919 struct dcerpc_do_request_out_frag *frag;
1920 size_t hdr_len = DCERPC_REQUEST_LENGTH;
1926 size_t data_thistime;
1927 size_t trailer_left;
1928 size_t trailer_thistime = 0;
1930 size_t total_thistime;
1932 union dcerpc_payload u;
1934 struct tevent_req *subreq;
1935 bool use_trans = true;
1937 if (state->object) {
1938 flags |= DCERPC_PFC_FLAG_OBJECT_UUID;
1943 * the fragment belongs to the connection instead of the request
1944 * because it has to remain in case the request is canceled
1946 frag = talloc_zero(state->conn, struct dcerpc_do_request_out_frag);
1947 if (tevent_req_nomem(frag, req)) {
1950 frag->ev = state->ev;
1951 frag->conn = state->conn;
1953 state->out_frag = frag;
1955 data_left = state->request.blob->length - state->request.ofs;
1956 trailer_left = state->request.trailer.length - state->request.trailer_ofs;
1957 total_left = data_left + trailer_left;
1958 if (total_left < data_left || total_left < trailer_left) {
1959 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
1963 status = dcerpc_guess_pdu_sizes(state->call->sec,
1964 hdr_len, total_left,
1965 state->conn->features.max_xmit_frag,
1968 &frag_len, &auth_len, &pad_len);
1969 if (!NT_STATUS_IS_OK(status)) {
1970 tevent_req_nterror(req, status);
1974 if (state->request.ofs == 0) {
1975 flags |= DCERPC_PFC_FLAG_FIRST;
1978 if (total_thistime == total_left) {
1979 flags |= DCERPC_PFC_FLAG_LAST;
1982 data_thistime = MIN(total_thistime, data_left);
1983 if (data_thistime < total_thistime) {
1984 trailer_thistime = total_thistime - data_thistime;
1987 ZERO_STRUCT(u.request);
1989 u.request.alloc_hint = total_left;
1990 u.request.context_id = state->call->pres->context_id;
1991 u.request.opnum = state->opnum;
1992 if (state->object) {
1993 u.request.object.object = *state->object;
1995 //TODO pass state->request.bigendian
1996 status = dcerpc_ncacn_packet_blob(frag,
2000 state->call->call_id,
2003 if (!NT_STATUS_IS_OK(status)) {
2004 tevent_req_nterror(req, status);
2008 /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
2009 * compute it right for requests because the auth trailer is missing
2011 dcerpc_set_frag_length(&frag->blob, frag_len);
2013 if (data_thistime > 0) {
2014 const uint8_t *data_ptr;
2016 data_ptr = state->request.blob->data;
2017 data_ptr += state->request.ofs;
2019 /* Copy in the data. */
2020 ok = data_blob_append(frag, &frag->blob,
2021 data_ptr, data_thistime);
2023 tevent_req_oom(req);
2027 state->request.ofs += data_thistime;
2030 if (trailer_thistime > 0) {
2031 const uint8_t *trailer_ptr;
2033 trailer_ptr = state->request.trailer.data;
2034 trailer_ptr += state->request.trailer_ofs;
2036 /* Copy in the data. */
2037 ok = data_blob_append(frag, &frag->blob,
2038 trailer_ptr, trailer_thistime);
2040 tevent_req_oom(req);
2044 state->request.trailer_ofs += trailer_thistime;
2047 switch (state->call->sec->auth_level) {
2048 case DCERPC_AUTH_LEVEL_NONE:
2049 case DCERPC_AUTH_LEVEL_CONNECT:
2050 case DCERPC_AUTH_LEVEL_PACKET:
2052 case DCERPC_AUTH_LEVEL_INTEGRITY:
2053 case DCERPC_AUTH_LEVEL_PRIVACY:
2054 status = dcerpc_response_auth_blob(state->call->sec,
2057 if (!NT_STATUS_IS_OK(status)) {
2058 tevent_req_nterror(req, status);
2063 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2067 frag->is_last = ((flags & DCERPC_PFC_FLAG_LAST) != 0);
2069 if (!frag->is_last) {
2073 if (frag->conn->transport.use_trans_fn == NULL) {
2077 if (frag->conn->loop.subreq != NULL) {
2081 if (frag->conn->features.concurrent_multiplex) {
2085 if (tevent_queue_length(frag->conn->calls.out_queue) > 1) {
2090 frag->subreq_wait1 = tevent_queue_wait_send(frag,
2092 frag->conn->transport.write_queue);
2093 if (tevent_req_nomem(req, frag->subreq_wait1)) {
2096 tevent_req_set_callback(frag->subreq_wait1,
2097 dcerpc_do_request_out_frag_trans_wait1,
2100 * we need to block reads until our write is
2101 * the next in the write queue.
2103 frag->conn->loop.subreq = frag->subreq_wait1;
2104 frag->conn->loop.ev = frag->ev;
2108 * We need to add a dcerpc_write_fragment_queue_send/recv()
2111 frag->vector.iov_base = frag->blob.data;
2112 frag->vector.iov_len = frag->blob.length;
2113 subreq = tstream_writev_queue_send(frag, frag->ev,
2114 frag->conn->transport.stream,
2115 frag->conn->transport.write_queue,
2117 if (tevent_req_nomem(subreq, req)) {
2120 tevent_req_set_callback(subreq,
2121 dcerpc_do_request_out_frag_done,
2125 frag->subreq_wait2 = tevent_queue_wait_send(frag,
2127 frag->conn->transport.write_queue);
2128 if (tevent_req_nomem(req, frag->subreq_wait2)) {
2131 tevent_req_set_callback(frag->subreq_wait2,
2132 dcerpc_do_request_out_frag_trans_wait2,
2136 if (!frag->is_last) {
2140 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2141 if (tevent_req_nterror(req, status)) {
2146 static void dcerpc_do_request_out_frag_trans_wait1(struct tevent_req *subreq)
2148 struct dcerpc_do_request_out_frag *frag =
2149 tevent_req_callback_data(subreq,
2150 struct dcerpc_do_request_out_frag);
2151 struct tevent_req *req = frag->req;
2156 * TODO; what if the caller has been free'ed?
2159 frag->subreq_wait1 = NULL;
2160 frag->conn->loop.subreq = NULL;
2162 ok = tevent_queue_wait_recv(subreq);
2164 status = NT_STATUS_INTERNAL_ERROR;
2167 tevent_req_nterror(req, status);
2169 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2173 if (tevent_queue_length(frag->conn->transport.write_queue) > 3) {
2175 * We added 3 entries into the queue,
2176 * wait1, writev and wait2.
2178 * There's more to write, we should not block
2179 * further writev calls for a trans call.
2181 * The wait2 stage will trigger the read.
2183 TALLOC_FREE(subreq);
2188 * we don't need wait2 anymore, we're sure that
2189 * we'll do a trans call.
2191 TALLOC_FREE(frag->subreq_wait2);
2193 status = frag->conn->transport.use_trans_fn(frag->conn->transport.stream);
2194 if (!NT_STATUS_IS_OK(status)) {
2197 tevent_req_nterror(req, status);
2199 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2203 /* we free subreq after tstream_cli_np_use_trans */
2204 TALLOC_FREE(subreq);
2206 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2207 if (!NT_STATUS_IS_OK(status)) {
2210 tevent_req_nterror(req, status);
2212 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2217 static void dcerpc_do_request_out_frag_done(struct tevent_req *subreq)
2219 struct dcerpc_do_request_out_frag *frag =
2220 tevent_req_callback_data(subreq,
2221 struct dcerpc_do_request_out_frag);
2222 struct tevent_req *req = frag->req;
2228 * If the caller has been free'ed, we have should
2229 * ignore any errors and just free 'frag'
2232 struct dcerpc_do_request_state *state =
2233 tevent_req_data(req,
2234 struct dcerpc_do_request_state);
2236 state->out_frag = NULL;
2239 ret = tstream_writev_queue_recv(subreq, &sys_errno);
2240 TALLOC_FREE(subreq);
2243 status = map_nt_error_from_unix_common(sys_errno);
2245 tevent_req_nterror(req, status);
2250 if (frag->subreq_wait2 != NULL) {
2254 if (frag->is_last) {
2264 dcerpc_do_request_out_frag_next(req, NULL);
2267 static void dcerpc_do_request_out_frag_trans_wait2(struct tevent_req *subreq)
2269 struct dcerpc_do_request_out_frag *frag =
2270 tevent_req_callback_data(subreq,
2271 struct dcerpc_do_request_out_frag);
2272 struct tevent_req *req = frag->req;
2276 frag->subreq_wait2 = NULL;
2278 ok = tevent_queue_wait_recv(subreq);
2280 status = NT_STATUS_INTERNAL_ERROR;
2283 tevent_req_nterror(req, status);
2285 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2289 TALLOC_FREE(subreq);
2291 status = dcerpc_connection_loop_restart(frag->conn, frag->ev);
2292 if (!NT_STATUS_IS_OK(status)) {
2295 tevent_req_nterror(req, status);
2297 //dcerpc_transport_dead(p, NT_STATUS_NO_MEMORY);
2303 /* we need to wait for incoming pdus */
2306 static NTSTATUS dcerpc_do_request_handle_in_frag(void *private_data,
2307 struct ncacn_packet *pkt,
2310 struct tevent_req *req =
2311 talloc_get_type_abort(private_data,
2313 struct dcerpc_do_request_state *state =
2314 tevent_req_data(req,
2315 struct dcerpc_do_request_state);
2324 /* Ensure we have the correct type. */
2325 switch (pkt->ptype) {
2326 case DCERPC_PKT_RESPONSE:
2328 /* Here's where we deal with incoming sign/seal. */
2329 error = dcerpc_check_pdu_auth(state->call->sec,
2331 &pkt->u.response.stub_and_verifier,
2332 DCERPC_RESPONSE_LENGTH,
2334 if (!NT_STATUS_IS_OK(error)) {
2338 if (!state->got_first) {
2339 state->got_first = true;
2341 if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
2342 return NT_STATUS_RPC_PROTOCOL_ERROR;
2345 state->conn->calls.active = state->call;
2347 if (pkt->drep[0] & DCERPC_DREP_LE) {
2348 state->response.bigendian = false;
2350 state->response.bigendian = true;
2353 if (state->verify_bitmask1) {
2354 state->call->sec->verified_bitmask1 = true;
2357 if (state->verify_pcontext) {
2358 state->call->pres->verified_pcontext = true;
2361 if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) {
2362 return NT_STATUS_RPC_PROTOCOL_ERROR;
2366 if (state->response.bigendian) {
2367 if (pkt->drep[0] != 0) {
2368 return NT_STATUS_RPC_PROTOCOL_ERROR;
2371 if (pkt->drep[0] != DCERPC_DREP_LE) {
2372 return NT_STATUS_RPC_PROTOCOL_ERROR;
2375 if (pkt->drep[1] != 0) {
2376 return NT_STATUS_RPC_PROTOCOL_ERROR;
2378 if (pkt->drep[2] != 0) {
2379 return NT_STATUS_RPC_PROTOCOL_ERROR;
2381 if (pkt->drep[3] != 0) {
2382 return NT_STATUS_RPC_PROTOCOL_ERROR;
2385 if (pkt->u.response.context_id != state->call->pres->context_id) {
2386 return NT_STATUS_RPC_PROTOCOL_ERROR;
2389 if (frag.length < DCERPC_RESPONSE_LENGTH + pad_len) {
2390 return NT_STATUS_RPC_PROTOCOL_ERROR;
2393 /* Point the return values at the NDR data. */
2394 payload.data = frag.data + DCERPC_RESPONSE_LENGTH;
2396 if (pkt->auth_length) {
2397 /* We've already done integer wrap tests in
2398 * dcerpc_check_auth(). */
2399 payload.length = frag.length
2400 - DCERPC_RESPONSE_LENGTH
2402 - DCERPC_AUTH_TRAILER_LENGTH
2405 payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
2408 DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
2409 (long unsigned int)frag.length,
2410 (long unsigned int)payload.length,
2411 (unsigned int)pad_len));
2414 * If this is the first reply, and the allocation hint is
2415 * reasonable, try and set up the reply_pdu DATA_BLOB to the
2419 if ((state->response.blob.length == 0) &&
2420 pkt->u.response.alloc_hint &&
2421 (pkt->u.response.alloc_hint < 15*1024*1024)) {
2422 ok = data_blob_realloc(state, &state->response.blob,
2423 pkt->u.response.alloc_hint);
2425 DEBUG(0, ("reply alloc hint %d too "
2426 "large to allocate\n",
2427 (int)pkt->u.response.alloc_hint));
2428 return NT_STATUS_NO_MEMORY;
2432 new_total = state->response.ofs + payload.length;
2434 if (new_total > 15 * 1024 *1024) {
2435 return NT_STATUS_RPC_PROTOCOL_ERROR;//TODO
2438 missing = new_total - state->response.blob.length;
2441 ok = data_blob_realloc(state, &state->response.blob,
2444 DEBUG(0, ("reply alloc hint %d too "
2445 "large to allocate\n",
2446 (int)pkt->u.response.alloc_hint));
2447 return NT_STATUS_NO_MEMORY;
2451 memcpy(state->response.blob.data + state->response.ofs,
2452 payload.data, payload.length);
2453 state->response.ofs += payload.length;
2455 if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
2456 tevent_req_done(req);//TODO
2457 return NT_STATUS_OK;
2460 return dcerpc_connection_loop_restart(state->conn, state->ev);
2462 case DCERPC_PKT_FAULT:
2464 DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault "
2465 "code %s received from %s!\n",
2466 dcerpc_errstr(talloc_tos(),
2467 pkt->u.fault.status),
2470 status = dcerpc_fault_to_nt_status(pkt->u.fault.status);
2471 if (NT_STATUS_IS_OK(status)) {
2472 status = NT_STATUS_RPC_PROTOCOL_ERROR;
2475 tevent_req_nterror(req, status);//TODO
2476 return NT_STATUS_OK;
2478 DEBUG(0, ("Unknown packet type %u received from %s!\n",
2479 (unsigned int)pkt->ptype,
2481 return NT_STATUS_RPC_PROTOCOL_ERROR;
2485 NTSTATUS dcerpc_do_request_recv(struct tevent_req *req,
2486 TALLOC_CTX *mem_ctx,
2487 DATA_BLOB *response,
2490 struct dcerpc_do_request_state *state =
2491 tevent_req_data(req,
2492 struct dcerpc_do_request_state);
2495 if (tevent_req_is_nterror(req, &status)) {
2496 tevent_req_received(req);
2500 /* return data to caller and assign it ownership of memory */
2501 response->data = talloc_move(mem_ctx, &state->response.blob.data);
2502 response->length = state->response.blob.length;
2503 *bigendian = state->response.bigendian;
2505 tevent_req_received(req);
2506 return NT_STATUS_OK;