Commit 935a41a0 authored by Colin Walters's avatar Colin Walters

2004-11-09 Colin Walters <walters@verbum.org>

	* dbus/dbus-string.c (_dbus_string_get_length): New
	function, writes DBusString to C buffer.

	* dbus/dbus-string.h: Prototype it.

	* dbus/dbus-message.c (dbus_message_type_to_string): New
	function, converts message type into C string.

	* dbus/dbus-message.h: Prototype it.

	* bus/selinux.c (bus_selinux_check): Take source pid,
	target pid, and audit data.  Pass audit data to
	avc_has_perm.
	(log_audit_callback): New function, appends extra
	audit information.
	(bus_selinux_allows_acquire_service): Also take
	service name, add it to audit data.
	(bus_selinux_allows_send): Also take message
	type, interface, method member, error name,
	and destination, and add them to audit data.
	(log_cb): Initialize func_audit.

	* bus/selinux.h (bus_selinux_allows_acquire_service)
	(bus_selinux_allows_send): Update prototypes

	* bus/services.c (bus_registry_acquire_service): Pass
	service name to bus_selinux_allows_acquire_service.

	* bus/bus.c (bus_context_check_security_policy): Pass
	additional audit data.  Move assignment of dest
	to its own line.
parent 2f5e9498
2004-11-09 Colin Walters <walters@verbum.org>
* dbus/dbus-string.c (_dbus_string_get_length): New
function, writes DBusString to C buffer.
* dbus/dbus-string.h: Prototype it.
* dbus/dbus-message.c (dbus_message_type_to_string): New
function, converts message type into C string.
* dbus/dbus-message.h: Prototype it.
* bus/selinux.c (bus_selinux_check): Take source pid,
target pid, and audit data. Pass audit data to
avc_has_perm.
(log_audit_callback): New function, appends extra
audit information.
(bus_selinux_allows_acquire_service): Also take
service name, add it to audit data.
(bus_selinux_allows_send): Also take message
type, interface, method member, error name,
and destination, and add them to audit data.
(log_cb): Initialize func_audit.
* bus/selinux.h (bus_selinux_allows_acquire_service)
(bus_selinux_allows_send): Update prototypes
* bus/services.c (bus_registry_acquire_service): Pass
service name to bus_selinux_allows_acquire_service.
* bus/bus.c (bus_context_check_security_policy): Pass
additional audit data. Move assignment of dest
to its own line.
2004-11-07 Colin Walters <walters@verbum.org>
* dbus/dbus-transport-unix.c (do_authentication): Always
......
......@@ -1127,12 +1127,20 @@ bus_context_check_security_policy (BusContext *context,
if (sender != NULL)
{
const char *dest;
dest = dbus_message_get_destination (message);
/* First verify the SELinux access controls. If allowed then
* go on with the standard checks.
*/
if (!bus_selinux_allows_send (sender, proposed_recipient))
if (!bus_selinux_allows_send (sender, proposed_recipient,
dbus_message_type_to_string (dbus_message_get_type (message)),
dbus_message_get_interface (message),
dbus_message_get_member (message),
dbus_message_get_error_name (message),
dest ? dest : DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
{
const char *dest = dbus_message_get_destination (message);
dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
"An SELinux policy prevents this sender "
"from sending this message to this recipient "
......@@ -1255,7 +1263,9 @@ bus_context_check_security_policy (BusContext *context,
proposed_recipient,
message))
{
const char *dest = dbus_message_get_destination (message);
const char *dest;
dest = dbus_message_get_destination (message);
dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
"A security policy in place prevents this sender "
"from sending this message to this recipient, "
......@@ -1280,7 +1290,9 @@ bus_context_check_security_policy (BusContext *context,
addressed_recipient, proposed_recipient,
message))
{
const char *dest = dbus_message_get_destination (message);
const char *dest;
dest = dbus_message_get_destination (message);
dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
"A security policy in place prevents this recipient "
"from receiving this message from this sender, "
......@@ -1304,7 +1316,9 @@ bus_context_check_security_policy (BusContext *context,
dbus_connection_get_outgoing_size (proposed_recipient) >
context->limits.max_outgoing_bytes)
{
const char *dest = dbus_message_get_destination (message);
const char *dest;
dest = dbus_message_get_destination (message);
dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
"The destination service \"%s\" has a full message queue",
dest ? dest : (proposed_recipient ?
......
......@@ -57,6 +57,7 @@ static pthread_t avc_notify_thread;
/* Prototypes for AVC callback functions. */
static void log_callback (const char *fmt, ...);
static void log_audit_callback (void *data, security_class_t class, char *buf, size_t bufleft);
static void *avc_create_thread (void (*run) (void));
static void avc_stop_thread (void *thread);
static void *avc_alloc_lock (void);
......@@ -73,7 +74,7 @@ static const struct avc_memory_callback mem_cb =
static const struct avc_log_callback log_cb =
{
.func_log = log_callback,
.func_audit = NULL
.func_audit = log_audit_callback
};
static const struct avc_thread_callback thread_cb =
{
......@@ -122,6 +123,18 @@ policy_reload_callback (u_int32_t event, security_id_t ssid,
return 0;
}
/**
* Log any auxiliary data
*/
static void
log_audit_callback (void *data, security_class_t class, char *buf, size_t bufleft)
{
DBusString *audmsg = data;
_dbus_string_copy_to_buffer (audmsg, buf, bufleft);
_dbus_string_free (audmsg);
dbus_free (audmsg);
}
/**
* Create thread to notify the AVC of enforcing and policy reload
* changes via netlink.
......@@ -349,17 +362,28 @@ static dbus_bool_t
bus_selinux_check (BusSELinuxID *sender_sid,
BusSELinuxID *override_sid,
security_class_t target_class,
access_vector_t requested)
access_vector_t requested,
unsigned long spid,
unsigned long tpid,
DBusString *auxdata)
{
if (!selinux_enabled)
return TRUE;
if (auxdata)
{
if (spid && _dbus_string_append (auxdata, " spid="))
_dbus_string_append_uint (auxdata, spid);
if (tpid && _dbus_string_append (auxdata, " tpid="))
_dbus_string_append_uint (auxdata, tpid);
}
/* Make the security check. AVC checks enforcing mode here as well. */
if (avc_has_perm (SELINUX_SID_FROM_BUS (sender_sid),
override_sid ?
SELINUX_SID_FROM_BUS (override_sid) :
SELINUX_SID_FROM_BUS (bus_sid),
target_class, requested, &aeref, NULL) < 0)
target_class, requested, &aeref, auxdata) < 0)
{
_dbus_verbose ("SELinux denying due to security policy.\n");
return FALSE;
......@@ -379,20 +403,40 @@ bus_selinux_check (BusSELinuxID *sender_sid,
*/
dbus_bool_t
bus_selinux_allows_acquire_service (DBusConnection *connection,
BusSELinuxID *service_sid)
BusSELinuxID *service_sid,
const char *service_name)
{
#ifdef HAVE_SELINUX
BusSELinuxID *connection_sid;
unsigned long spid;
DBusString *auxdata;
if (!selinux_enabled)
return TRUE;
connection_sid = bus_connection_get_selinux_id (connection);
if (!dbus_connection_get_unix_process_id (connection, &spid))
spid = 0;
auxdata = dbus_new0 (DBusString, 1);
if (auxdata)
{
if (!_dbus_string_init (auxdata))
{
dbus_free (auxdata);
auxdata = NULL;
}
else if (_dbus_string_append (auxdata, "service="))
_dbus_string_append (auxdata, service_name);
}
return bus_selinux_check (connection_sid,
service_sid,
SECCLASS_DBUS,
DBUS__ACQUIRE_SVC);
service_sid,
SECCLASS_DBUS,
DBUS__ACQUIRE_SVC,
spid,
0,
auxdata);
#else
return TRUE;
#endif /* HAVE_SELINUX */
......@@ -410,15 +454,50 @@ bus_selinux_allows_acquire_service (DBusConnection *connection,
*/
dbus_bool_t
bus_selinux_allows_send (DBusConnection *sender,
DBusConnection *proposed_recipient)
DBusConnection *proposed_recipient,
const char *msgtype,
const char *interface,
const char *member,
const char *error_name,
const char *destination)
{
#ifdef HAVE_SELINUX
BusSELinuxID *recipient_sid;
BusSELinuxID *sender_sid;
unsigned long spid, tpid;
DBusString *auxdata;
if (!selinux_enabled)
return TRUE;
if (!dbus_connection_get_unix_process_id (sender, &spid))
spid = 0;
if (!dbus_connection_get_unix_process_id (proposed_recipient, &tpid))
tpid = 0;
auxdata = dbus_new0 (DBusString, 1);
if (auxdata)
{
if (!_dbus_string_init (auxdata))
{
dbus_free (auxdata);
auxdata = NULL;
}
else
{
if (_dbus_string_append (auxdata, "msgtype="))
_dbus_string_append (auxdata, msgtype);
if (interface && _dbus_string_append (auxdata, " interface="))
_dbus_string_append (auxdata, interface);
if (member && _dbus_string_append (auxdata, " member="))
_dbus_string_append (auxdata, member);
if (error_name && _dbus_string_append (auxdata, " error_name="))
_dbus_string_append (auxdata, error_name);
if (destination && _dbus_string_append (auxdata, " dest="))
_dbus_string_append (auxdata, destination);
}
}
sender_sid = bus_connection_get_selinux_id (sender);
/* A NULL proposed_recipient means the bus itself. */
if (proposed_recipient)
......@@ -427,7 +506,8 @@ bus_selinux_allows_send (DBusConnection *sender,
recipient_sid = BUS_SID_FROM_SELINUX (bus_sid);
return bus_selinux_check (sender_sid, recipient_sid,
SECCLASS_DBUS, DBUS__SEND_MSG);
SECCLASS_DBUS, DBUS__SEND_MSG,
spid, tpid, auxdata);
#else
return TRUE;
#endif /* HAVE_SELINUX */
......
......@@ -47,11 +47,15 @@ const char* bus_selinux_get_policy_root (void);
dbus_bool_t bus_selinux_allows_acquire_service (DBusConnection *connection,
BusSELinuxID *service_sid);
BusSELinuxID *service_sid,
const char *service_name);
dbus_bool_t bus_selinux_allows_send (DBusConnection *sender,
DBusConnection *proposed_recipient);
DBusConnection *proposed_recipient,
const char *msgtype, /* Supplementary audit data */
const char *interface,
const char *member,
const char *error_name,
const char *destination);
BusSELinuxID* bus_selinux_init_connection_id (DBusConnection *connection,
DBusError *error);
......
......@@ -310,7 +310,8 @@ bus_registry_acquire_service (BusRegistry *registry,
sid = bus_selinux_id_table_lookup (registry->service_sid_table,
service_name);
if (!bus_selinux_allows_acquire_service (connection, sid))
if (!bus_selinux_allows_acquire_service (connection, sid,
_dbus_string_get_const_data (service_name)))
{
dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
"Connection \"%s\" is not allowed to own the service \"%s\" due "
......
......@@ -5778,6 +5778,37 @@ dbus_message_type_from_string (const char *type_str)
return DBUS_MESSAGE_TYPE_INVALID;
}
/**
* Utility function to convert a D-BUS message type into a
* machine-readable string (not translated).
*
* @code
* DBUS_MESSAGE_TYPE_METHOD_CALL -> "method_call"
* DBUS_MESSAGE_TYPE_METHOD_RETURN -> "method_return"
* DBUS_MESSAGE_TYPE_SIGNAL -> "signal"
* DBUS_MESSAGE_TYPE_ERROR -> "error"
* DBUS_MESSAGE_TYPE_INVALID -> "invalid"
* @endcode
*
*/
const char *
dbus_message_type_to_string (int type)
{
switch (type)
{
case DBUS_MESSAGE_TYPE_METHOD_CALL:
return "method_call";
case DBUS_MESSAGE_TYPE_METHOD_RETURN:
return "method_return";
case DBUS_MESSAGE_TYPE_SIGNAL:
return "signal";
case DBUS_MESSAGE_TYPE_ERROR:
return "error";
default:
return "invalid";
}
}
/** @} */
#ifdef DBUS_BUILD_TESTS
#include "dbus-test.h"
......
......@@ -295,6 +295,7 @@ void* dbus_message_get_data (DBusMessage *message,
dbus_int32_t slot);
int dbus_message_type_from_string (const char *type_str);
const char * dbus_message_type_to_string (int type);
DBUS_END_DECLS
......
......@@ -756,6 +756,30 @@ _dbus_string_copy_data_len (const DBusString *str,
return TRUE;
}
/**
* Copies the contents of a DBusString into a different
* buffer. The resulting buffer will be nul-terminated.
*
* @param str a string
* @param buffer a C buffer to copy data to
* @param len maximum length of C buffer
*/
void
_dbus_string_copy_to_buffer (const DBusString *str,
char *buffer,
int avail_len)
{
int copy_len;
DBUS_CONST_STRING_PREAMBLE (str);
_dbus_assert (avail_len >= 0);
copy_len = MIN (avail_len, real->len+1);
memcpy (buffer, real->str, copy_len);
if (avail_len > 0 && avail_len == copy_len)
buffer[avail_len-1] = '\0';
}
/**
* Gets the length of a string (not including nul termination).
*
......
......@@ -88,6 +88,9 @@ dbus_bool_t _dbus_string_copy_data_len (const DBusString *str,
char **data_return,
int start,
int len);
void _dbus_string_copy_to_buffer (const DBusString *str,
char *buffer,
int len);
int _dbus_string_get_length (const DBusString *str);
dbus_bool_t _dbus_string_lengthen (DBusString *str,
int additional_length);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment