STEP01: librpc/rpc/dcerpc_connection.c: fail dcerpc_do_bind without successful presen...
authorStefan Metzmacher <metze@samba.org>
Wed, 22 Jan 2014 09:15:21 +0000 (10:15 +0100)
committerStefan Metzmacher <metze@samba.org>
Tue, 4 Jun 2019 10:45:39 +0000 (12:45 +0200)
librpc/rpc/dcerpc_connection.c

index 899aeabc457ae36418ffd13cf0f6d95fb3c49e7d..16694433dddf813de059f10e65785d7c21a1874f 100644 (file)
@@ -1548,6 +1548,8 @@ static NTSTATUS dcerpc_do_bind_handle_in_frag(void *private_data,
                tevent_req_data(req,
                struct dcerpc_do_bind_state);
        NTSTATUS status;
+       struct dcerpc_presentation *last_pres = NULL;
+       size_t num_pres_ok = 0;
        size_t i;
 
        /* Ensure we have the correct type. */
@@ -1598,7 +1600,29 @@ static NTSTATUS dcerpc_do_bind_handle_in_frag(void *private_data,
                        struct dcerpc_ack_ctx *ack = &pkt->u.bind_ack.ctx_list[i];
 
                        if (i < state->num_pres) {
-                               state->pres[i]->negotiate.ack = *ack;
+                               struct dcerpc_ack_ctx *pack =
+                                       &state->pres[i]->negotiate.ack;
+
+                               if (ack->result == DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK) {
+                                       return NT_STATUS_RPC_PROTOCOL_ERROR;
+                               }
+
+                               if (ack->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
+                                       *pack = *ack;
+                                       num_pres_ok += 1;
+                                       continue;
+                               }
+
+                               if (pack->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
+                                       /*
+                                        * if a presentation context was valid it must
+                                        * be valid for the lifetime of the connection
+                                        */
+                                       return NT_STATUS_RPC_PROTOCOL_ERROR;
+                               }
+
+                               *pack = *ack;
+                               last_pres = state->pres[i];
                                continue;
                        }
 
@@ -1625,6 +1649,12 @@ static NTSTATUS dcerpc_do_bind_handle_in_frag(void *private_data,
                        }
                }
 
+               if (num_pres_ok == 0 && last_pres != NULL) {
+                       status = dcerpc_presentation_status(last_pres);
+                       tevent_req_nterror(req, status);
+                       return NT_STATUS_OK;
+               }
+
                if (pkt->auth_length >= 8) {
                        struct tevent_req *subreq;