STEP01: librpc/rpc/dcerpc_connection.c active
authorStefan Metzmacher <metze@samba.org>
Mon, 13 Jan 2014 15:42:35 +0000 (16:42 +0100)
committerStefan Metzmacher <metze@samba.org>
Tue, 4 Jun 2019 10:45:39 +0000 (12:45 +0200)
librpc/rpc/dcerpc_connection.c

index f674d9d3055fd25cd1190242d24473a235fda68a..c72ac47c7eba84c55e0335cf2393b86ddf609dc8 100644 (file)
@@ -1669,6 +1669,7 @@ struct dcerpc_do_request_state {
        } request;
        bool verify_bitmask1;
        bool verify_pcontext;
+       bool got_first;
        struct dcerpc_do_request_out_frag *out_frag;
        struct {
                DATA_BLOB blob;
@@ -1763,6 +1764,9 @@ static void dcerpc_do_request_cleanup(struct tevent_req *req,
        }
 
        if (state->call != NULL) {
+               if (state->call == state->conn->calls.active) {
+                       state->conn->calls.active = NULL;
+               }
                ZERO_STRUCT(state->call->incoming);
                DLIST_REMOVE(state->conn->calls.list, state->call);
                state->call = NULL;
@@ -2331,12 +2335,55 @@ static NTSTATUS dcerpc_do_request_handle_in_frag(void *private_data,
                        return error;
                }
 
-               if (state->verify_bitmask1) {
-                       state->call->sec->verified_bitmask1 = true;
+               if (!state->got_first) {
+                       state->got_first = true;
+
+                       if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
+                               return NT_STATUS_RPC_PROTOCOL_ERROR;
+                       }
+
+                       state->conn->calls.active = state->call;
+
+                       if (pkt->drep[0] & DCERPC_DREP_LE) {
+                               state->response.bigendian = false;
+                       } else {
+                               state->response.bigendian = true;
+                       }
+
+                       if (state->verify_bitmask1) {
+                               state->call->sec->verified_bitmask1 = true;
+                       }
+
+                       if (state->verify_pcontext) {
+                               state->call->pres->verified_pcontext = true;
+                       }
+               } else {
+                       if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) {
+                               return NT_STATUS_RPC_PROTOCOL_ERROR;
+                       }
+               }
+
+               if (state->response.bigendian) {
+                       if (pkt->drep[0] != 0) {
+                               return NT_STATUS_RPC_PROTOCOL_ERROR;
+                       }
+               } else {
+                       if (pkt->drep[0] != DCERPC_DREP_LE) {
+                               return NT_STATUS_RPC_PROTOCOL_ERROR;
+                       }
+               }
+               if (pkt->drep[1] != 0) {
+                       return NT_STATUS_RPC_PROTOCOL_ERROR;
+               }
+               if (pkt->drep[2] != 0) {
+                       return NT_STATUS_RPC_PROTOCOL_ERROR;
+               }
+               if (pkt->drep[3] != 0) {
+                       return NT_STATUS_RPC_PROTOCOL_ERROR;
                }
 
-               if (state->verify_pcontext) {
-                       state->call->pres->verified_pcontext = true;
+               if (pkt->u.response.context_id != state->call->pres->context_id) {
+                       return NT_STATUS_RPC_PROTOCOL_ERROR;
                }
 
                if (frag.length < DCERPC_RESPONSE_LENGTH + pad_len) {
@@ -2358,14 +2405,6 @@ static NTSTATUS dcerpc_do_request_handle_in_frag(void *private_data,
                        payload.length = frag.length - DCERPC_RESPONSE_LENGTH;
                }
 
-               if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
-                       if (pkt->drep[0] & DCERPC_DREP_LE) {
-                               state->response.bigendian = false;
-                       } else {
-                               state->response.bigendian = true;
-                       }
-               }
-
                DEBUG(10, ("Got pdu len %lu, data_len %lu, ss_len %u\n",
                           (long unsigned int)frag.length,
                           (long unsigned int)payload.length,