2004-11-09 Colin Walters <walters@verbum.org>
authorColin Walters <walters@verbum.org>
Tue, 9 Nov 2004 06:11:33 +0000 (06:11 +0000)
committerColin Walters <walters@verbum.org>
Tue, 9 Nov 2004 06:11:33 +0000 (06:11 +0000)
* 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.

ChangeLog
bus/bus.c
bus/selinux.c
bus/selinux.h
bus/services.c
dbus/dbus-message.c
dbus/dbus-message.h
dbus/dbus-string.c
dbus/dbus-string.h

index 612db5d..118fa6f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+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
index 65e396c..a80636b 100644 (file)
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -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 ?
index 0a3dec7..9527489 100644 (file)
@@ -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 =
 {
@@ -123,6 +124,18 @@ policy_reload_callback (u_int32_t event, security_id_t ssid,
 }
 
 /**
+ * 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 */
index 71271fa..3627126 100644 (file)
@@ -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);
index 31041c3..1036947 100644 (file)
@@ -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 "
index b191337..df0ade2 100644 (file)
@@ -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"
index 50ec22c..e1894c7 100644 (file)
@@ -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
 
index 2061e8b..7381dab 100644 (file)
@@ -757,6 +757,30 @@ _dbus_string_copy_data_len (const DBusString  *str,
 }
 
 /**
+ * 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).
  *
  * @returns the length.
index 2dda2b0..1a0236d 100644 (file)
@@ -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);