mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
CVE-2016-2118: s4:rpc_server: make it possible to define a min_auth_level on a presentation context
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11616 Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Günther Deschner <gd@samba.org>
This commit is contained in:
parent
c52097ae17
commit
51aa7bd311
@ -510,6 +510,35 @@ static int dcesrv_connection_context_destructor(struct dcesrv_connection_context
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
|
||||
{
|
||||
struct dcesrv_connection_context *context = dce_call->context;
|
||||
|
||||
context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
|
||||
}
|
||||
|
||||
NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
|
||||
const struct dcesrv_interface *iface)
|
||||
{
|
||||
if (dce_call->context == NULL) {
|
||||
return NT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
|
||||
const struct dcesrv_interface *iface)
|
||||
{
|
||||
if (dce_call->context == NULL) {
|
||||
return NT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
dce_call->context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
handle a bind request
|
||||
*/
|
||||
@ -597,6 +626,8 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
|
||||
call->context = context;
|
||||
talloc_set_destructor(context, dcesrv_connection_context_destructor);
|
||||
|
||||
dcesrv_prepare_context_auth(call);
|
||||
|
||||
status = iface->bind(call, iface, if_version);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
char *uuid_str = GUID_string(call, &uuid);
|
||||
@ -781,6 +812,8 @@ static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_
|
||||
call->context = context;
|
||||
talloc_set_destructor(context, dcesrv_connection_context_destructor);
|
||||
|
||||
dcesrv_prepare_context_auth(call);
|
||||
|
||||
status = iface->bind(call, iface, if_version);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
/* we don't want to trigger the iface->unbind() hook */
|
||||
@ -982,9 +1015,14 @@ done:
|
||||
*/
|
||||
static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
|
||||
{
|
||||
const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
|
||||
enum dcerpc_transport_t transport =
|
||||
dcerpc_binding_get_transport(endpoint->ep_description);
|
||||
struct ndr_pull *pull;
|
||||
NTSTATUS status;
|
||||
struct dcesrv_connection_context *context;
|
||||
uint32_t auth_type = DCERPC_AUTH_TYPE_NONE;
|
||||
uint32_t auth_level = DCERPC_AUTH_LEVEL_NONE;
|
||||
|
||||
/* if authenticated, and the mech we use can't do async replies, don't use them... */
|
||||
if (call->conn->auth_state.gensec_security &&
|
||||
@ -997,6 +1035,28 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
|
||||
return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
|
||||
}
|
||||
|
||||
if (call->conn->auth_state.auth_info != NULL) {
|
||||
auth_type = call->conn->auth_state.auth_info->auth_type;
|
||||
auth_level = call->conn->auth_state.auth_info->auth_level;
|
||||
}
|
||||
|
||||
if (auth_level < context->min_auth_level) {
|
||||
char *addr;
|
||||
|
||||
addr = tsocket_address_string(call->conn->remote_address, call);
|
||||
|
||||
DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
|
||||
"to [%s] with auth[type=0x%x,level=0x%x] "
|
||||
"on [%s] from [%s]\n",
|
||||
__func__,
|
||||
context->min_auth_level,
|
||||
context->iface->name,
|
||||
auth_type, auth_level,
|
||||
derpc_transport_string_by_transport(transport),
|
||||
addr));
|
||||
return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
|
||||
}
|
||||
|
||||
pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
|
||||
NT_STATUS_HAVE_NO_MEMORY(pull);
|
||||
|
||||
|
@ -173,6 +173,11 @@ struct dcesrv_connection_context {
|
||||
|
||||
/* private data for the interface implementation */
|
||||
void *private_data;
|
||||
|
||||
/*
|
||||
* the minimum required auth level for this interface
|
||||
*/
|
||||
enum dcerpc_AuthLevel min_auth_level;
|
||||
};
|
||||
|
||||
|
||||
@ -419,5 +424,9 @@ _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call);
|
||||
*/
|
||||
_PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call);
|
||||
|
||||
_PUBLIC_ NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
|
||||
const struct dcesrv_interface *iface);
|
||||
_PUBLIC_ NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
|
||||
const struct dcesrv_interface *iface);
|
||||
|
||||
#endif /* SAMBA_DCERPC_SERVER_H */
|
||||
|
Loading…
Reference in New Issue
Block a user