s4:rpc_server: implement DCERPC_PFC_FLAG_CONC_MPX ordering restrictions
authorStefan Metzmacher <metze@samba.org>
Fri, 16 Sep 2016 10:35:54 +0000 (12:35 +0200)
committerAndreas Schneider <asn@cryptomilk.org>
Wed, 26 Oct 2016 09:20:17 +0000 (11:20 +0200)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
source4/rpc_server/dcerpc_server.c

index 9f6c8dc444d3e0a8c629b6a22456b6e3d910a326..bc030489d85db6aca1946a7891901e912163f137 100644 (file)
@@ -1619,10 +1619,33 @@ static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
                }
 
                if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
+                       if (dce_conn->pending_call_list != NULL) {
+                               /*
+                                * concurrent requests are only allowed
+                                * if DCERPC_PFC_FLAG_CONC_MPX was negotiated.
+                                */
+                               if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
+                                       dcesrv_call_disconnect_after(call,
+                                               "dcesrv_auth_request - "
+                                               "existing pending call without CONN_MPX");
+                                       return dcesrv_fault(call,
+                                               DCERPC_NCA_S_PROTO_ERROR);
+                               }
+                       }
                        /* only one request is possible in the fragmented list */
                        if (dce_conn->incoming_fragmented_call_list != NULL) {
-                               TALLOC_FREE(call);
-                               call = dce_conn->incoming_fragmented_call_list;
+                               if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
+                                       /*
+                                        * Without DCERPC_PFC_FLAG_CONC_MPX
+                                        * we need to return the FAULT on the
+                                        * already existing call.
+                                        *
+                                        * This is important to get the
+                                        * call_id and context_id right.
+                                        */
+                                       TALLOC_FREE(call);
+                                       call = dce_conn->incoming_fragmented_call_list;
+                               }
                                dcesrv_call_disconnect_after(call,
                                        "dcesrv_auth_request - "
                                        "existing fragmented call");