dcesrv_core: introduce dcesrv_connection->transport_max_recv_frag
authorStefan Metzmacher <metze@samba.org>
Thu, 12 Nov 2020 15:38:32 +0000 (16:38 +0100)
committerStefan Metzmacher <metze@samba.org>
Tue, 23 Apr 2024 16:16:45 +0000 (18:16 +0200)
The max fragment size depends on the transport.

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

Signed-off-by: Stefan Metzmacher <metze@samba.org>
librpc/rpc/dcesrv_core.c
librpc/rpc/dcesrv_core.h
selftest/knownfail.d/dcerpc-transport-xmit [deleted file]

index e4308cfa348b965fc3c6b94702312d9d633509d3..695fbf9eadb42ee7daa299a0b83bee19db470042 100644 (file)
@@ -36,6 +36,7 @@
 #include "system/network.h"
 #include "lib/util/idtree_random.h"
 #include "nsswitch/winbind_client.h"
+#include "libcli/smb/tstream_smbXcli_np.h"
 
 /**
  * @file
@@ -676,6 +677,8 @@ _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
 {
        struct dcesrv_auth *auth = NULL;
        struct dcesrv_connection *p = NULL;
+       enum dcerpc_transport_t transport =
+               dcerpc_binding_get_transport(ep->ep_description);
 
        if (!session_info) {
                return NT_STATUS_ACCESS_DENIED;
@@ -695,9 +698,21 @@ _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
        p->event_ctx = event_ctx;
        p->state_flags = state_flags;
        p->allow_bind = true;
-       p->max_recv_frag = 5840;
-       p->max_xmit_frag = 5840;
        p->max_total_request_size = DCERPC_NCACN_REQUEST_DEFAULT_MAX_SIZE;
+       /*
+        * SMB uses 4280, while all others use 5480
+        * note that p->transport_max_recv_frag is fixed
+        * for the lifetime of the connection, it's not
+        * negotiated by bind.
+        */
+       if (transport == NCACN_NP) {
+               p->transport_max_recv_frag = TSTREAM_SMBXCLI_NP_MAX_BUF_SIZE;
+       } else {
+               p->transport_max_recv_frag = DCERPC_FRAG_MAX_SIZE;
+       }
+       /* these might be overwritten by BIND */
+       p->max_recv_frag = p->transport_max_recv_frag;
+       p->max_xmit_frag = p->transport_max_recv_frag;
 
        p->support_hdr_signing = lpcfg_parm_bool(dce_ctx->lp_ctx,
                                                 NULL,
@@ -1117,12 +1132,20 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
                        DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
        }
 
+       /*
+        * Note that BIND and ALTER allow frag_len up to UINT16_MAX,
+        * so we don't check again frag_len against
+        * call->conn->transport_max_recv_frag
+        */
+
        /* max_recv_frag and max_xmit_frag result always in the same value! */
        max_req = MIN(call->pkt.u.bind.max_xmit_frag,
                      call->pkt.u.bind.max_recv_frag);
        /*
         * The values are between 2048 and 5840 tested against Windows 2012R2
         * via ncacn_ip_tcp on port 135.
+        *
+        * call->conn->transport_max_recv_frag stays fixed at 5840 (4280 for SMB)
         */
        max_req = MAX(2048, max_req);
        max_rep = MIN(max_req, conn->max_recv_frag);
@@ -1777,6 +1800,12 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
                return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
        }
 
+       /*
+        * Note that BIND and ALTER allow frag_len up to UINT16_MAX,
+        * so we don't check again frag_len against
+        * call->conn->transport_max_recv_frag
+        */
+
        auth_ok = dcesrv_auth_alter(call);
        if (!auth_ok) {
                if (call->fault_code != 0) {
@@ -2322,14 +2351,15 @@ static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
                                        DCERPC_NCA_S_PROTO_ERROR);
                }
 
-               if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
+               if (call->pkt.frag_length > call->conn->transport_max_recv_frag) {
                        /*
                         * We don't use dcesrv_fault_disconnect()
                         * here, because we don't want to set
                         * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
                         *
                         * Note that we don't check against the negotiated
-                        * max_recv_frag, but a hard coded value.
+                        * max_recv_frag, but a hard coded value from
+                        * the transport.
                         */
                        return dcesrv_fault_disconnect0(call, DCERPC_NCA_S_PROTO_ERROR);
                }
index 4148981719f0a1d09dbfc5b2609e975f0b666c59..5db35d42aa40262ffd98665cb7699065da0052a8 100644 (file)
@@ -272,6 +272,7 @@ struct dcesrv_connection {
        struct dcesrv_call_state *call_list;
 
        /* the maximum size the client wants to receive */
+       uint16_t transport_max_recv_frag;
        uint16_t max_recv_frag;
        uint16_t max_xmit_frag;
 
diff --git a/selftest/knownfail.d/dcerpc-transport-xmit b/selftest/knownfail.d/dcerpc-transport-xmit
deleted file mode 100644 (file)
index e070c15..0000000
+++ /dev/null
@@ -1 +0,0 @@
-^samba.tests.dcerpc.raw_protocol.samba.tests.dcerpc.raw_protocol.TestDCERPC_BIND.test_neg_xmit_ffff_ffff_smb