CVE-2021-23192: dcesrv_core: add dcesrv_fault_disconnect0() that skips DCERPC_PFC_FLA...
authorStefan Metzmacher <metze@samba.org>
Fri, 13 Nov 2020 10:27:19 +0000 (11:27 +0100)
committerJule Anger <janger@samba.org>
Mon, 8 Nov 2021 09:46:45 +0000 (10:46 +0100)
That makes the callers much simpler and allow better debugging.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14875

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Samuel Cabrero <scabrero@samba.org>
librpc/rpc/dcesrv_core.c

index 0c2d83b4b174bff44ade814a3be709db00085bfe..ffaa9019d4b87b4bce02be1296052d2a21a12130 100644 (file)
@@ -736,6 +736,9 @@ static NTSTATUS _dcesrv_fault_disconnect_flags(struct dcesrv_call_state *call,
        _dcesrv_fault_disconnect_flags(call, fault_code, \
                DCERPC_PFC_FLAG_DID_NOT_EXECUTE, \
                __func__, __location__)
+#define dcesrv_fault_disconnect0(call, fault_code) \
+       _dcesrv_fault_disconnect_flags(call, fault_code, 0, \
+               __func__, __location__)
 
 static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
 {
@@ -2097,10 +2100,7 @@ static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
                         * Note that we don't check against the negotiated
                         * max_recv_frag, but a hard coded value.
                         */
-                       dcesrv_call_disconnect_after(call,
-                               "dcesrv_auth_request - frag_length too large");
-                       return dcesrv_fault(call,
-                                       DCERPC_NCA_S_PROTO_ERROR);
+                       return dcesrv_fault_disconnect0(call, DCERPC_NCA_S_PROTO_ERROR);
                }
 
                if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
@@ -2110,10 +2110,7 @@ static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
                                 * 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,
+                                       return dcesrv_fault_disconnect0(call,
                                                DCERPC_NCA_S_PROTO_ERROR);
                                }
                        }
@@ -2131,10 +2128,7 @@ static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
                                        TALLOC_FREE(call);
                                        call = dce_conn->incoming_fragmented_call_list;
                                }
-                               dcesrv_call_disconnect_after(call,
-                                       "dcesrv_auth_request - "
-                                       "existing fragmented call");
-                               return dcesrv_fault(call,
+                               return dcesrv_fault_disconnect0(call,
                                                DCERPC_NCA_S_PROTO_ERROR);
                        }
                        if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_PENDING_CANCEL) {
@@ -2155,10 +2149,7 @@ static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
                        existing = dcesrv_find_fragmented_call(dce_conn,
                                                        call->pkt.call_id);
                        if (existing == NULL) {
-                               dcesrv_call_disconnect_after(call,
-                                       "dcesrv_auth_request - "
-                                       "no existing fragmented call");
-                               return dcesrv_fault(call,
+                               return dcesrv_fault_disconnect0(call,
                                                DCERPC_NCA_S_PROTO_ERROR);
                        }
                        er = &existing->pkt.u.request;
@@ -2211,12 +2202,10 @@ static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
                         * here, because we don't want to set
                         * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
                         */
-                       dcesrv_call_disconnect_after(call,
-                                               "dcesrv_auth_request - failed");
                        if (call->fault_code == 0) {
                                call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
                        }
-                       return dcesrv_fault(call, call->fault_code);
+                       return dcesrv_fault_disconnect0(call, call->fault_code);
                }
        }
 
@@ -2233,20 +2222,17 @@ static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
                 */
                available = dce_conn->max_total_request_size;
                if (er->stub_and_verifier.length > available) {
-                       dcesrv_call_disconnect_after(existing,
-                               "dcesrv_auth_request - existing payload too large");
-                       return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
+                       return dcesrv_fault_disconnect0(existing,
+                                       DCERPC_FAULT_ACCESS_DENIED);
                }
                available -= er->stub_and_verifier.length;
                if (nr->alloc_hint > available) {
-                       dcesrv_call_disconnect_after(existing,
-                               "dcesrv_auth_request - alloc hint too large");
-                       return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
+                       return dcesrv_fault_disconnect0(existing,
+                                       DCERPC_FAULT_ACCESS_DENIED);
                }
                if (nr->stub_and_verifier.length > available) {
-                       dcesrv_call_disconnect_after(existing,
-                               "dcesrv_auth_request - new payload too large");
-                       return dcesrv_fault(existing, DCERPC_FAULT_ACCESS_DENIED);
+                       return dcesrv_fault_disconnect0(existing,
+                                       DCERPC_FAULT_ACCESS_DENIED);
                }
                alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
                /* allocate at least 1 byte */
@@ -2285,9 +2271,8 @@ static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
                 * Up to 4 MByte are allowed by all fragments
                 */
                if (call->pkt.u.request.alloc_hint > dce_conn->max_total_request_size) {
-                       dcesrv_call_disconnect_after(call,
-                               "dcesrv_auth_request - initial alloc hint too large");
-                       return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
+                       return dcesrv_fault_disconnect0(call,
+                                       DCERPC_FAULT_ACCESS_DENIED);
                }
                dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
                return NT_STATUS_OK;