diff options
| -rw-r--r-- | bus/bus.c | 42 | ||||
| -rw-r--r-- | bus/connection.c | 105 | ||||
| -rw-r--r-- | bus/connection.h | 1 | ||||
| -rw-r--r-- | dbus/dbus-sysdeps-util-unix.c | 96 | ||||
| -rw-r--r-- | dbus/dbus-sysdeps.h | 5 | 
5 files changed, 228 insertions, 21 deletions
@@ -1168,6 +1168,8 @@ bus_context_check_security_policy (BusContext     *context,    int type;    dbus_bool_t requested_reply;    const char *sender_name; +  const char *sender_loginfo; +  const char *proposed_recipient_loginfo;    type = dbus_message_get_type (message);    dest = dbus_message_get_destination (message); @@ -1182,9 +1184,20 @@ bus_context_check_security_policy (BusContext     *context,    /* Used in logging below */    if (sender != NULL) -    sender_name = bus_connection_get_name (sender); +    { +      sender_name = bus_connection_get_name (sender); +      sender_loginfo = bus_connection_get_loginfo (sender); +    } +  else +    { +      sender_name = NULL; +      sender_loginfo = "(bus)"; +    } +   +  if (proposed_recipient != NULL) +    proposed_recipient_loginfo = bus_connection_get_loginfo (proposed_recipient);    else -    sender_name = NULL; +    proposed_recipient_loginfo = "bus";    switch (type)      { @@ -1347,32 +1360,35 @@ bus_context_check_security_policy (BusContext     *context,                                           message, &toggles, &log))      {        const char *msg = "Rejected send message, %d matched rules; " -                        "type=\"%s\", sender=\"%s\" interface=\"%s\" member=\"%s\" error name=\"%s\" destination=\"%s\")"; - +                        "type=\"%s\", sender=\"%s\" (%s) interface=\"%s\" member=\"%s\" error name=\"%s\" destination=\"%s\" (%s))";        dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, msg,                        toggles,                        dbus_message_type_to_string (dbus_message_get_type (message)),                        sender_name ? sender_name : "(unset)", +                      sender_loginfo,                        dbus_message_get_interface (message) ?                        dbus_message_get_interface (message) : "(unset)",                        dbus_message_get_member (message) ?                        dbus_message_get_member (message) : "(unset)",                        dbus_message_get_error_name (message) ?                        dbus_message_get_error_name (message) : "(unset)", -                      dest ? dest : DBUS_SERVICE_DBUS); +                      dest ? dest : DBUS_SERVICE_DBUS, +                      proposed_recipient_loginfo);        /* Needs to be duplicated to avoid calling malloc and having to handle OOM */        bus_context_log_security (context, msg,                                  toggles,                                  dbus_message_type_to_string (dbus_message_get_type (message)),                                  sender_name ? sender_name : "(unset)", +                                sender_loginfo,                                  dbus_message_get_interface (message) ?                                  dbus_message_get_interface (message) : "(unset)",                                  dbus_message_get_member (message) ?                                  dbus_message_get_member (message) : "(unset)",                                  dbus_message_get_error_name (message) ?                                  dbus_message_get_error_name (message) : "(unset)", -                                dest ? dest : DBUS_SERVICE_DBUS); +                                dest ? dest : DBUS_SERVICE_DBUS, +                                proposed_recipient_loginfo);        _dbus_verbose ("security policy disallowing message due to sender policy\n");        return FALSE;      } @@ -1401,35 +1417,39 @@ bus_context_check_security_policy (BusContext     *context,                                              message, &toggles))      {        const char *msg = "Rejected receive message, %d matched rules; " -                        "type=\"%s\" sender=\"%s\" interface=\"%s\" member=\"%s\" error name=\"%s\" destination=\"%s\" reply serial=%u requested_reply=%d)"; +                        "type=\"%s\" sender=\"%s\" (%s) interface=\"%s\" member=\"%s\" error name=\"%s\" reply serial=%u requested_reply=%d destination=\"%s\" (%s))";        dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, msg,                        toggles,                        dbus_message_type_to_string (dbus_message_get_type (message)),                        sender_name ? sender_name : "(unset)", +                      sender_loginfo,                        dbus_message_get_interface (message) ?                        dbus_message_get_interface (message) : "(unset)",                        dbus_message_get_member (message) ?                        dbus_message_get_member (message) : "(unset)",                        dbus_message_get_error_name (message) ?                        dbus_message_get_error_name (message) : "(unset)", -                      dest ? dest : DBUS_SERVICE_DBUS,                        dbus_message_get_reply_serial (message), -                      requested_reply); +                      requested_reply, +                      dest ? dest : DBUS_SERVICE_DBUS, +                      proposed_recipient_loginfo);        /* Needs to be duplicated to avoid calling malloc and having to handle OOM */        bus_context_log_security (context, msg,                                  toggles,                                  dbus_message_type_to_string (dbus_message_get_type (message)),                                  sender_name ? sender_name : "(unset)", +                                sender_loginfo,                                  dbus_message_get_interface (message) ?                                  dbus_message_get_interface (message) : "(unset)",                                  dbus_message_get_member (message) ?                                  dbus_message_get_member (message) : "(unset)",                                  dbus_message_get_error_name (message) ?                                  dbus_message_get_error_name (message) : "(unset)", -                                dest ? dest : DBUS_SERVICE_DBUS,                                  dbus_message_get_reply_serial (message), -                                requested_reply); +                                requested_reply, +                                dest ? dest : DBUS_SERVICE_DBUS, +                                proposed_recipient_loginfo);        _dbus_verbose ("security policy disallowing message due to recipient policy\n");        return FALSE;      } diff --git a/bus/connection.c b/bus/connection.c index ed1b1391..ab99fa5f 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -32,6 +32,9 @@  #include <dbus/dbus-hash.h>  #include <dbus/dbus-timeout.h> +/* Trim executed commands to this length; we want to keep logs readable */ +#define MAX_LOG_COMMAND_LEN 50 +  static void bus_connection_remove_transactions (DBusConnection *connection);  typedef struct @@ -76,6 +79,7 @@ typedef struct    DBusPreallocatedSend *oom_preallocated;    BusClientPolicy *policy; +  char *cached_loginfo_string;    BusSELinuxID *selinux_id;    long connection_tv_sec;  /**< Time when we connected (seconds component) */ @@ -406,6 +410,8 @@ free_connection_data (void *data)    if (d->selinux_id)      bus_selinux_id_unref (d->selinux_id); +  dbus_free (d->cached_loginfo_string); +      dbus_free (d->name);    dbus_free (d); @@ -537,13 +543,73 @@ bus_connections_unref (BusConnections *connections)      }  } +/* Used for logging */ +static dbus_bool_t +cache_peer_loginfo_string (BusConnectionData *d,  +                           DBusConnection    *connection) +{ +  DBusString loginfo_buf; +  unsigned long uid; +  unsigned long pid; +  char *windows_sid; +  dbus_bool_t prev_added; + +  if (!_dbus_string_init (&loginfo_buf)) +    return FALSE; +   +  prev_added = FALSE; +  if (dbus_connection_get_unix_user (connection, &uid)) +    { +      if (!_dbus_string_append_printf (&loginfo_buf, "uid=%ld", uid)) +        goto oom; +      else +        prev_added = TRUE; +    } + +  if (dbus_connection_get_unix_process_id (connection, &pid)) +    { +      if (prev_added) +        { +          if (!_dbus_string_append_byte (&loginfo_buf, ' ')) +            goto oom; +        } +      if (!_dbus_string_append_printf (&loginfo_buf, "pid=%ld comm=\"", pid)) +        goto oom; +      /* Ignore errors here */ +      if (_dbus_command_for_pid (pid, &loginfo_buf, MAX_LOG_COMMAND_LEN, NULL)) +        { +          if (!_dbus_string_append_byte (&loginfo_buf, '"')) +            goto oom; +        } +    } + +  if (dbus_connection_get_windows_user (connection, &windows_sid)) +    { +      if (!_dbus_string_append_printf (&loginfo_buf, "sid=\"%s\" ", windows_sid)) +        goto oom; +      dbus_free (windows_sid); +    } + +  if (!_dbus_string_steal_data (&loginfo_buf, &(d->cached_loginfo_string))) +    goto oom; + +  _dbus_string_free (&loginfo_buf);  + +  return TRUE; +oom: +   _dbus_string_free (&loginfo_buf); +   return FALSE; +} +  dbus_bool_t  bus_connections_setup_connection (BusConnections *connections,                                    DBusConnection *connection)  { +    BusConnectionData *d;    dbus_bool_t retval;    DBusError error; +    d = dbus_new0 (BusConnectionData, 1); @@ -583,7 +649,7 @@ bus_connections_setup_connection (BusConnections *connections,        dbus_error_free (&error);        goto out;      } -   +    if (!dbus_connection_set_watch_functions (connection,                                              add_connection_watch,                                              remove_connection_watch, @@ -842,6 +908,18 @@ bus_connection_is_in_unix_group (DBusConnection *connection,    return FALSE;  } +const char * +bus_connection_get_loginfo (DBusConnection        *connection) +{ +  BusConnectionData *d; +     +  d = BUS_CONNECTION_DATA (connection); + +  if (!bus_connection_is_active (connection)) +    return "inactive"; +  return d->cached_loginfo_string;   +} +  BusClientPolicy*  bus_connection_get_policy (DBusConnection *connection)  { @@ -1302,16 +1380,15 @@ bus_connection_complete (DBusConnection   *connection,      {        if (!adjust_connections_for_uid (d->connections,                                         uid, 1)) -        { -          BUS_SET_OOM (error); -          dbus_free (d->name); -          d->name = NULL; -          bus_client_policy_unref (d->policy); -          d->policy = NULL; -          return FALSE; -        } +        goto fail;      } -   + +  /* Create and cache a string which holds information about the  +   * peer process; used for logging purposes. +   */ +  if (!cache_peer_loginfo_string (d, connection)) +    goto fail; +    /* Now the connection is active, move it between lists */    _dbus_list_unlink (&d->connections->incomplete,                       d->link_in_connection_list); @@ -1329,6 +1406,14 @@ bus_connection_complete (DBusConnection   *connection,    _dbus_assert (bus_connection_is_active (connection));    return TRUE; +fail: +  BUS_SET_OOM (error); +  dbus_free (d->name); +  d->name = NULL; +  if (d->policy) +    bus_client_policy_unref (d->policy); +  d->policy = NULL; +  return FALSE;  }  const char * diff --git a/bus/connection.h b/bus/connection.h index 5099bcf9..4f352169 100644 --- a/bus/connection.h +++ b/bus/connection.h @@ -50,6 +50,7 @@ BusConnections* bus_connection_get_connections    (DBusConnection  BusRegistry*    bus_connection_get_registry       (DBusConnection               *connection);  BusActivation*  bus_connection_get_activation     (DBusConnection               *connection);  BusMatchmaker*  bus_connection_get_matchmaker     (DBusConnection               *connection); +const char *    bus_connection_get_loginfo        (DBusConnection        *connection);  BusSELinuxID*   bus_connection_get_selinux_id     (DBusConnection               *connection);  dbus_bool_t     bus_connections_check_limits      (BusConnections               *connections,                                                     DBusConnection               *requesting_completion, diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c index 3f2a2330..6ca662b2 100644 --- a/dbus/dbus-sysdeps-util-unix.c +++ b/dbus/dbus-sysdeps-util-unix.c @@ -1132,3 +1132,99 @@ _dbus_string_get_dirname  (const DBusString *filename,  }  /** @} */ /* DBusString stuff */ +static void +string_squash_nonprintable (DBusString *str) +{ +  char *buf; +  int i, len;  +   +  buf = _dbus_string_get_data (str); +  len = _dbus_string_get_length (str); +   +  for (i = 0; i < len; i++) +    if (buf[i] == '\0') +      buf[i] = ' '; +    else if (buf[i] < 0x20 || buf[i] > 127) +      buf[i] = '?'; +} + +/** + * Get a printable string describing the command used to execute + * the process with pid.  This string should only be used for + * informative purposes such as logging; it may not be trusted. + *  + * The command is guaranteed to be printable ASCII and no longer + * than max_len. + *  + * @param pid Process id + * @param str Append command to this string + * @param max_len Maximum length of returned command + * @param error return location for errors + * @returns #FALSE on error + */ +dbus_bool_t  +_dbus_command_for_pid (unsigned long  pid, +                       DBusString    *str, +                       int            max_len, +                       DBusError     *error) +{ +  /* This is all Linux-specific for now */ +  DBusString path; +  DBusString cmdline; +  int fd; +   +  if (!_dbus_string_init (&path))  +    { +      _DBUS_SET_OOM (error); +      return FALSE; +    } +   +  if (!_dbus_string_init (&cmdline)) +    { +      _DBUS_SET_OOM (error); +      _dbus_string_free (&path); +      return FALSE; +    } +   +  if (!_dbus_string_append_printf (&path, "/proc/%ld/cmdline", pid)) +    goto oom; +   +  fd = open (_dbus_string_get_const_data (&path), O_RDONLY); +  if (fd < 0)  +    { +      dbus_set_error (error, +                      _dbus_error_from_errno (errno), +                      "Failed to open \"%s\": %s", +                      _dbus_string_get_const_data (&path), +                      _dbus_strerror (errno)); +      goto fail; +    } +   +  if (!_dbus_read (fd, &cmdline, max_len)) +    { +      dbus_set_error (error, +                      _dbus_error_from_errno (errno), +                      "Failed to read from \"%s\": %s", +                      _dbus_string_get_const_data (&path), +                      _dbus_strerror (errno));       +      goto fail; +    } +   +  if (!_dbus_close (fd, error)) +    goto fail; +   +  string_squash_nonprintable (&cmdline);   +   +  if (!_dbus_string_copy (&cmdline, 0, str, _dbus_string_get_length (str))) +    goto oom; +   +  _dbus_string_free (&cmdline);   +  _dbus_string_free (&path); +  return TRUE; +oom: +  _DBUS_SET_OOM (error); +fail: +  _dbus_string_free (&cmdline); +  _dbus_string_free (&path); +  return FALSE; +}
\ No newline at end of file diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 5f4b00e1..2662b270 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -411,6 +411,11 @@ dbus_bool_t _dbus_write_pid_to_file_and_pipe (const DBusString *pidfile,                                                dbus_pid_t        pid_to_write,                                                DBusError        *error); +dbus_bool_t _dbus_command_for_pid (unsigned long  pid, +                                   DBusString    *str, +                                   int            max_len, +                                   DBusError     *error); +  /** A UNIX signal handler */  typedef void (* DBusSignalHandler) (int sig);  | 
