diff --git a/librpc/rpc/dcesrv_auth.c b/librpc/rpc/dcesrv_auth.c index c5dbec973d1..b2f6e607a24 100644 --- a/librpc/rpc/dcesrv_auth.c +++ b/librpc/rpc/dcesrv_auth.c @@ -445,11 +445,38 @@ bool dcesrv_auth_prepare_auth3(struct dcesrv_call_state *call) struct dcesrv_auth *auth = call->auth_state; NTSTATUS status; - if (pkt->auth_length == 0) { + if (pkt->frag_length > call->conn->transport_max_recv_frag) { + /* + * Note that we don't check against the negotiated + * max_recv_frag, but a hard coded value from + * the transport. + */ + call->fault_code = DCERPC_NCA_S_PROTO_ERROR; + return false; + } + + if (pkt->auth_length > 4096) { + call->fault_code = DCERPC_NCA_S_PROTO_ERROR; return false; } if (auth->auth_finished) { + call->fault_code = DCERPC_NCA_S_PROTO_ERROR; + return false; + } + + if (!auth->auth_started) { + call->fault_code = DCERPC_NCA_S_PROTO_ERROR; + return false; + } + + if (auth->auth_invalid) { + call->fault_code = DCERPC_NCA_S_PROTO_ERROR; + return false; + } + + if (pkt->auth_length == 0) { + call->fault_code = DCERPC_NCA_S_FAULT_REMOTE_NO_MEMORY; return false; } @@ -465,23 +492,36 @@ bool dcesrv_auth_prepare_auth3(struct dcesrv_call_state *call) status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.auth3.auth_info, &call->in_auth_info, NULL, true); if (!NT_STATUS_IS_OK(status)) { + struct dcerpc_auth *auth_info = &call->in_auth_info; + uint32_t nr = auth_info->auth_context_id; + /* * Windows returns DCERPC_NCA_S_FAULT_REMOTE_NO_MEMORY - * instead of DCERPC_NCA_S_PROTO_ERROR. + * instead of DCERPC_NCA_S_PROTO_ERROR in most cases. */ call->fault_code = DCERPC_NCA_S_FAULT_REMOTE_NO_MEMORY; + + if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR) && + nr != DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED) + { + call->fault_code = DCERPC_NCA_S_PROTO_ERROR; + } + return false; } if (call->in_auth_info.auth_type != auth->auth_type) { + call->fault_code = DCERPC_NCA_S_FAULT_REMOTE_NO_MEMORY; return false; } if (call->in_auth_info.auth_level != auth->auth_level) { + call->fault_code = DCERPC_NCA_S_FAULT_REMOTE_NO_MEMORY; return false; } if (call->in_auth_info.auth_context_id != auth->auth_context_id) { + call->fault_code = DCERPC_FAULT_ACCESS_DENIED; return false; } diff --git a/librpc/rpc/dcesrv_core.c b/librpc/rpc/dcesrv_core.c index ebe6e662202..66478001640 100644 --- a/librpc/rpc/dcesrv_core.c +++ b/librpc/rpc/dcesrv_core.c @@ -1419,14 +1419,6 @@ static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call) struct tevent_req *subreq = NULL; NTSTATUS status; - if (!auth->auth_started) { - return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR); - } - - if (auth->auth_finished) { - return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR); - } - status = dcerpc_verify_ncacn_packet_header(&call->pkt, DCERPC_PKT_AUTH3, call->pkt.u.auth3.auth_info.length, diff --git a/selftest/knownfail.d/dcerpc-auth-pad b/selftest/knownfail.d/dcerpc-auth-pad deleted file mode 100644 index 4c77d622737..00000000000 --- a/selftest/knownfail.d/dcerpc-auth-pad +++ /dev/null @@ -1,3 +0,0 @@ -^samba.tests.dcerpc.raw_protocol.samba.tests.dcerpc.raw_protocol.TestDCERPC_BIND.test_auth_pad_auth3_align2_ntlm -^samba.tests.dcerpc.raw_protocol.samba.tests.dcerpc.raw_protocol.TestDCERPC_BIND.test_auth_pad_auth3_align2_spnego -^samba.tests.dcerpc.raw_protocol.samba.tests.dcerpc.raw_protocol.TestDCERPC_BIND.test_auth_tail_pad_spnego_auth3