mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
CVE-2015-5370: s4:rpc_server: verify the protocol headers before processing pdus
On protocol errors we should send BIND_NAK or FAULT and mark the connection as to be terminated. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11344 Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Günther Deschner <gd@samba.org>
This commit is contained in:
parent
caa1e75661
commit
c0d74ca7af
@ -452,6 +452,18 @@ static void dcesrv_call_set_list(struct dcesrv_call_state *call,
|
||||
}
|
||||
}
|
||||
|
||||
static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
|
||||
const char *reason)
|
||||
{
|
||||
if (call->conn->terminate != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
call->terminate_reason = talloc_strdup(call, reason);
|
||||
if (call->terminate_reason == NULL) {
|
||||
call->terminate_reason = __location__;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
return a dcerpc bind_nak
|
||||
@ -464,6 +476,12 @@ static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
|
||||
NTSTATUS status;
|
||||
static const uint8_t _pad[3] = { 0, };
|
||||
|
||||
/*
|
||||
* We add the call to the pending_call_list
|
||||
* in order to defer the termination.
|
||||
*/
|
||||
dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
|
||||
|
||||
/* setup a bind_nak */
|
||||
dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
|
||||
pkt.auth_length = 0;
|
||||
@ -501,6 +519,19 @@ static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS dcesrv_fault_disconnect(struct dcesrv_call_state *call,
|
||||
uint32_t fault_code)
|
||||
{
|
||||
/*
|
||||
* We add the call to the pending_call_list
|
||||
* in order to defer the termination.
|
||||
*/
|
||||
dcesrv_call_disconnect_after(call, "dcesrv_fault_disconnect");
|
||||
|
||||
return dcesrv_fault_with_flags(call, fault_code,
|
||||
DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
|
||||
}
|
||||
|
||||
static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
|
||||
{
|
||||
DLIST_REMOVE(c->conn->contexts, c);
|
||||
@ -641,6 +672,23 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
|
||||
const char *ep_prefix = "";
|
||||
const char *endpoint = NULL;
|
||||
|
||||
status = dcerpc_verify_ncacn_packet_header(&call->pkt,
|
||||
DCERPC_PKT_BIND,
|
||||
call->pkt.u.bind.auth_info.length,
|
||||
0, /* required flags */
|
||||
DCERPC_PFC_FLAG_FIRST |
|
||||
DCERPC_PFC_FLAG_LAST |
|
||||
DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
|
||||
0x08 | /* this is not defined, but should be ignored */
|
||||
DCERPC_PFC_FLAG_CONC_MPX |
|
||||
DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
|
||||
DCERPC_PFC_FLAG_MAYBE |
|
||||
DCERPC_PFC_FLAG_OBJECT_UUID);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return dcesrv_bind_nak(call,
|
||||
DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
@ -864,6 +912,24 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
|
||||
*/
|
||||
static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
status = dcerpc_verify_ncacn_packet_header(&call->pkt,
|
||||
DCERPC_PKT_AUTH3,
|
||||
call->pkt.u.auth3.auth_info.length,
|
||||
0, /* required flags */
|
||||
DCERPC_PFC_FLAG_FIRST |
|
||||
DCERPC_PFC_FLAG_LAST |
|
||||
DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
|
||||
0x08 | /* this is not defined, but should be ignored */
|
||||
DCERPC_PFC_FLAG_CONC_MPX |
|
||||
DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
|
||||
DCERPC_PFC_FLAG_MAYBE |
|
||||
DCERPC_PFC_FLAG_OBJECT_UUID);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
|
||||
}
|
||||
|
||||
/* handle the auth3 in the auth code */
|
||||
if (!dcesrv_auth_auth3(call)) {
|
||||
return dcesrv_fault(call, DCERPC_FAULT_OTHER);
|
||||
@ -1033,6 +1099,22 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
|
||||
NTSTATUS status;
|
||||
uint32_t context_id;
|
||||
|
||||
status = dcerpc_verify_ncacn_packet_header(&call->pkt,
|
||||
DCERPC_PKT_ALTER,
|
||||
call->pkt.u.alter.auth_info.length,
|
||||
0, /* required flags */
|
||||
DCERPC_PFC_FLAG_FIRST |
|
||||
DCERPC_PFC_FLAG_LAST |
|
||||
DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
|
||||
0x08 | /* this is not defined, but should be ignored */
|
||||
DCERPC_PFC_FLAG_CONC_MPX |
|
||||
DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
|
||||
DCERPC_PFC_FLAG_MAYBE |
|
||||
DCERPC_PFC_FLAG_OBJECT_UUID);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
|
||||
}
|
||||
|
||||
/* handle any authentication that is being requested */
|
||||
if (!dcesrv_auth_alter(call)) {
|
||||
/* TODO: work out the right reject code */
|
||||
@ -1310,9 +1392,27 @@ static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
|
||||
|
||||
/* we have to check the signing here, before combining the
|
||||
pdus */
|
||||
if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
|
||||
!dcesrv_auth_request(call, &blob)) {
|
||||
return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
|
||||
if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
|
||||
status = dcerpc_verify_ncacn_packet_header(&call->pkt,
|
||||
DCERPC_PKT_REQUEST,
|
||||
call->pkt.u.request.stub_and_verifier.length,
|
||||
0, /* required_flags */
|
||||
DCERPC_PFC_FLAG_FIRST |
|
||||
DCERPC_PFC_FLAG_LAST |
|
||||
DCERPC_PFC_FLAG_PENDING_CANCEL |
|
||||
0x08 | /* this is not defined, but should be ignored */
|
||||
DCERPC_PFC_FLAG_CONC_MPX |
|
||||
DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
|
||||
DCERPC_PFC_FLAG_MAYBE |
|
||||
DCERPC_PFC_FLAG_OBJECT_UUID);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return dcesrv_fault_disconnect(call,
|
||||
DCERPC_NCA_S_PROTO_ERROR);
|
||||
}
|
||||
|
||||
if (!dcesrv_auth_request(call, &blob)) {
|
||||
return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
|
||||
}
|
||||
}
|
||||
|
||||
/* see if this is a continued packet */
|
||||
|
Loading…
Reference in New Issue
Block a user