diff options
| -rw-r--r-- | bus/driver.c | 79 | ||||
| -rw-r--r-- | configure.in | 20 | ||||
| -rw-r--r-- | dbus/dbus-auth.c | 7 | ||||
| -rw-r--r-- | dbus/dbus-connection.c | 34 | ||||
| -rw-r--r-- | dbus/dbus-connection.h | 3 | ||||
| -rw-r--r-- | dbus/dbus-credentials.c | 79 | ||||
| -rw-r--r-- | dbus/dbus-credentials.h | 3 | ||||
| -rw-r--r-- | dbus/dbus-protocol.h | 2 | ||||
| -rw-r--r-- | dbus/dbus-sysdeps-unix.c | 35 | ||||
| -rw-r--r-- | dbus/dbus-transport.c | 34 | ||||
| -rw-r--r-- | dbus/dbus-transport.h | 3 | 
11 files changed, 296 insertions, 3 deletions
| diff --git a/bus/driver.c b/bus/driver.c index 25196265..bdf5afbe 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -1273,6 +1273,81 @@ bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection,  }  static dbus_bool_t +bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection, +					      BusTransaction *transaction, +					      DBusMessage    *message, +					      DBusError      *error) +{ +  const char *service; +  DBusString str; +  BusRegistry *registry; +  BusService *serv; +  DBusConnection *conn; +  DBusMessage *reply; +  char *data = NULL; +  dbus_uint32_t data_size; + +  _DBUS_ASSERT_ERROR_IS_CLEAR (error); + +  registry = bus_connection_get_registry (connection); + +  service = NULL; +  reply = NULL; + +  if (! dbus_message_get_args (message, error, +			       DBUS_TYPE_STRING, &service, +			       DBUS_TYPE_INVALID)) +      goto failed; + +  _dbus_verbose ("asked for audit session data for connection %s\n", service); + +  _dbus_string_init_const (&str, service); +  serv = bus_registry_lookup (registry, &str); +  if (serv == NULL) +    { +      dbus_set_error (error,  +		      DBUS_ERROR_NAME_HAS_NO_OWNER, +		      "Could not get audit session data for name '%s': no such name", service); +      goto failed; +    } + +  conn = bus_service_get_primary_owners_connection (serv); + +  reply = dbus_message_new_method_return (message); +  if (reply == NULL) +    goto oom; + +  if (!dbus_connection_get_adt_audit_session_data (conn, &data, &data_size) || data == NULL) +    { +      dbus_set_error (error, +                      DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN, +                      "Could not determine audit session data for '%s'", service); +      goto failed; +    } + +  if (! dbus_message_append_args (reply, +                                  DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, data_size, +                                  DBUS_TYPE_INVALID)) +    goto oom; + +  if (! bus_transaction_send_from_driver (transaction, connection, reply)) +    goto oom; + +  dbus_message_unref (reply); + +  return TRUE; + + oom: +  BUS_SET_OOM (error); + + failed: +  _DBUS_ASSERT_ERROR_IS_SET (error); +  if (reply) +    dbus_message_unref (reply); +  return FALSE; +} + +static dbus_bool_t  bus_driver_handle_get_connection_selinux_security_context (DBusConnection *connection,  							   BusTransaction *transaction,  							   DBusMessage    *message, @@ -1503,6 +1578,10 @@ struct      DBUS_TYPE_STRING_AS_STRING,      DBUS_TYPE_UINT32_AS_STRING,      bus_driver_handle_get_connection_unix_process_id }, +  { "GetAdtAuditSessionData", +    DBUS_TYPE_STRING_AS_STRING, +    DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING, +    bus_driver_handle_get_adt_audit_session_data },    { "GetConnectionSELinuxSecurityContext",      DBUS_TYPE_STRING_AS_STRING,      DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING, diff --git a/configure.in b/configure.in index 7130a8ce..b8338405 100644 --- a/configure.in +++ b/configure.in @@ -1028,6 +1028,24 @@ if test x$have_libaudit = xyes ; then      AC_DEFINE(HAVE_LIBAUDIT,1,[audit daemon SELinux support])  fi +# Check for ADT API +AC_MSG_CHECKING(for ADT API) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include <bsm/adt.h> +adt_user_context = ADT_USER; +]], [[]])], [ check_adt_audit=yes ], [ check_adt_audit=no ]) + +if test ${check_adt_audit} = yes +then +   AC_DEFINE([HAVE_ADT], [], [Adt audit API]) +   ADT_LIBS="-lbsm" +   LIBS="-lbsm $LIBS" +   AC_MSG_RESULT(yes) +else +   AC_MSG_RESULT(no) +fi + +  #### Set up final flags  DBUS_CLIENT_CFLAGS=  DBUS_CLIENT_LIBS="$THREAD_LIBS" @@ -1035,7 +1053,7 @@ AC_SUBST(DBUS_CLIENT_CFLAGS)  AC_SUBST(DBUS_CLIENT_LIBS)  DBUS_BUS_CFLAGS="$XML_CFLAGS" -DBUS_BUS_LIBS="$XML_LIBS $SELINUX_LIBS $INTLLIBS $THREAD_LIBS" +DBUS_BUS_LIBS="$XML_LIBS $SELINUX_LIBS $INTLLIBS $THREAD_LIBS $ADT_LIBS"  AC_SUBST(DBUS_BUS_CFLAGS)  AC_SUBST(DBUS_BUS_LIBS) diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c index 7e424aff..ec7cf312 100644 --- a/dbus/dbus-auth.c +++ b/dbus/dbus-auth.c @@ -1094,6 +1094,13 @@ handle_server_data_external_mech (DBusAuth         *auth,                                               DBUS_CREDENTIAL_UNIX_PROCESS_ID,                                               auth->credentials))          return FALSE; + +      /* also copy audit data from the socket credentials +       */ +      if (!_dbus_credentials_add_credential (auth->authorized_identity, +                                             DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID, +                                             auth->credentials)) +        return FALSE;        if (!send_ok (auth))          return FALSE; diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index f2902ed4..804af828 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -4986,6 +4986,40 @@ dbus_connection_get_unix_process_id (DBusConnection *connection,  }  /** + * Gets the ADT audit data of the connection if any. + * Returns #TRUE if the structure pointer is returned. + * Always returns #FALSE prior to authenticating the + * connection. + * + * @param connection the connection + * @param data return location for audit data  + * @returns #TRUE if audit data is filled in with a valid ucred pointer + */ +dbus_bool_t +dbus_connection_get_adt_audit_session_data (DBusConnection *connection, +					    void          **data, +					    dbus_int32_t   *data_size) +{ +  dbus_bool_t result; + +  _dbus_return_val_if_fail (connection != NULL, FALSE); +  _dbus_return_val_if_fail (data != NULL, FALSE); +  _dbus_return_val_if_fail (data_size != NULL, FALSE); +   +  CONNECTION_LOCK (connection); + +  if (!_dbus_transport_get_is_authenticated (connection->transport)) +    result = FALSE; +  else +    result = _dbus_transport_get_adt_audit_session_data (connection->transport, +					    	         data, +			  			         data_size); +  CONNECTION_UNLOCK (connection); + +  return result; +} + +/**   * Sets a predicate function used to determine whether a given user ID   * is allowed to connect. When an incoming connection has   * authenticated with a particular user ID, this function is called; diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index 5d7e493b..b8fd35fb 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -231,6 +231,9 @@ dbus_bool_t        dbus_connection_get_unix_user                (DBusConnection                                                                   unsigned long              *uid);  dbus_bool_t        dbus_connection_get_unix_process_id          (DBusConnection             *connection,                                                                   unsigned long              *pid); +dbus_bool_t        dbus_connection_get_adt_audit_session_data   (DBusConnection             *connection, +                                                                 void                      **data, +                                                                 dbus_int32_t               *data_size);  void               dbus_connection_set_unix_user_function       (DBusConnection             *connection,                                                                   DBusAllowUnixUserFunction   function,                                                                   void                       *data, diff --git a/dbus/dbus-credentials.c b/dbus/dbus-credentials.c index 790ca06b..f21ecb27 100644 --- a/dbus/dbus-credentials.c +++ b/dbus/dbus-credentials.c @@ -50,6 +50,8 @@ struct DBusCredentials {    dbus_uid_t unix_uid;    dbus_pid_t unix_pid;    char *windows_sid; +  void *adt_audit_data; +  dbus_int32_t adt_audit_data_size;  };  /** @} */ @@ -77,6 +79,8 @@ _dbus_credentials_new (void)    creds->unix_uid = DBUS_UID_UNSET;    creds->unix_pid = DBUS_PID_UNSET;    creds->windows_sid = NULL; +  creds->adt_audit_data = NULL; +  creds->adt_audit_data_size = 0;    return creds;  } @@ -129,6 +133,7 @@ _dbus_credentials_unref (DBusCredentials    *credentials)    if (credentials->refcount == 0)      {        dbus_free (credentials->windows_sid); +      dbus_free (credentials->adt_audit_data);        dbus_free (credentials);      }  } @@ -188,6 +193,31 @@ _dbus_credentials_add_windows_sid (DBusCredentials    *credentials,  }  /** + * Add ADT audit data to the credentials. + * + * @param credentials the object + * @param audit_data the audit data + * @param size the length of audit data + * @returns #FALSE if no memory + */ +dbus_bool_t +_dbus_credentials_add_adt_audit_data (DBusCredentials    *credentials, +                                      void               *audit_data, +                                      dbus_int32_t        size) +{ +  void *copy; +  copy = _dbus_memdup (audit_data, size); +  if (copy == NULL) +    return FALSE; + +  dbus_free (credentials->adt_audit_data); +  credentials->adt_audit_data = copy; +  credentials->adt_audit_data_size = size; + +  return TRUE; +} + +/**   * Checks whether the given credential is present.   *   * @param credentials the object @@ -206,6 +236,8 @@ _dbus_credentials_include (DBusCredentials    *credentials,        return credentials->unix_uid != DBUS_UID_UNSET;      case DBUS_CREDENTIAL_WINDOWS_SID:        return credentials->windows_sid != NULL; +    case DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID: +      return credentials->adt_audit_data != NULL;      }    _dbus_assert_not_reached ("Unknown credential enum value"); @@ -252,6 +284,32 @@ _dbus_credentials_get_windows_sid (DBusCredentials    *credentials)  }  /** + * Gets the ADT audit data in the credentials, or #NULL if + * the credentials object doesn't contain ADT audit data. + * + * @param credentials the object + * @returns Solaris ADT audit data  + */ +void * +_dbus_credentials_get_adt_audit_data (DBusCredentials    *credentials) +{ +  return credentials->adt_audit_data; +} + +/** + * Gets the ADT audit data size in the credentials, or 0 if + * the credentials object doesn't contain ADT audit data. + * + * @param credentials the object + * @returns Solaris ADT audit data size + */ +dbus_int32_t  +_dbus_credentials_get_adt_audit_data_size (DBusCredentials    *credentials) +{ +  return credentials->adt_audit_data_size; +} + +/**   * Checks whether the first credentials object contains   * all the credentials found in the second credentials object.   * @@ -270,7 +328,11 @@ _dbus_credentials_are_superset (DBusCredentials    *credentials,       possible_subset->unix_uid == credentials->unix_uid) &&      (possible_subset->windows_sid == NULL ||       (credentials->windows_sid && strcmp (possible_subset->windows_sid, -                                          credentials->windows_sid) == 0)); +                                          credentials->windows_sid) == 0)) && +    (possible_subset->adt_audit_data == NULL || +     (credentials->adt_audit_data && memcmp (possible_subset->adt_audit_data, +                                             credentials->adt_audit_data, +                                             credentials->adt_audit_data_size) == 0));  }  /** @@ -285,7 +347,8 @@ _dbus_credentials_are_empty (DBusCredentials    *credentials)    return      credentials->unix_pid == DBUS_PID_UNSET &&      credentials->unix_uid == DBUS_UID_UNSET && -    credentials->windows_sid == NULL; +    credentials->windows_sid == NULL && +    credentials->adt_audit_data == NULL;  }  /** @@ -322,6 +385,9 @@ _dbus_credentials_add_credentials (DBusCredentials    *credentials,                                        DBUS_CREDENTIAL_UNIX_USER_ID,                                        other_credentials) &&      _dbus_credentials_add_credential (credentials, +                                      DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID, +                                      other_credentials) && +    _dbus_credentials_add_credential (credentials,                                        DBUS_CREDENTIAL_WINDOWS_SID,                                        other_credentials);  } @@ -360,6 +426,12 @@ _dbus_credentials_add_credential (DBusCredentials    *credentials,      {        if (!_dbus_credentials_add_windows_sid (credentials, other_credentials->windows_sid))          return FALSE; +    }  +  else if (which == DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID && +           other_credentials->adt_audit_data != NULL)  +    { +      if (!_dbus_credentials_add_adt_audit_data (credentials, other_credentials->adt_audit_data, other_credentials->adt_audit_data_size)) +        return FALSE;      }    return TRUE; @@ -377,6 +449,9 @@ _dbus_credentials_clear (DBusCredentials    *credentials)    credentials->unix_uid = DBUS_UID_UNSET;    dbus_free (credentials->windows_sid);    credentials->windows_sid = NULL; +  dbus_free (credentials->adt_audit_data); +  credentials->adt_audit_data = NULL; +  credentials->adt_audit_data_size = 0;  }  /** diff --git a/dbus/dbus-credentials.h b/dbus/dbus-credentials.h index b8d7dd7a..d4c8d160 100644 --- a/dbus/dbus-credentials.h +++ b/dbus/dbus-credentials.h @@ -33,6 +33,7 @@ DBUS_BEGIN_DECLS  typedef enum {    DBUS_CREDENTIAL_UNIX_PROCESS_ID,    DBUS_CREDENTIAL_UNIX_USER_ID, +  DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID,    DBUS_CREDENTIAL_WINDOWS_SID  } DBusCredentialType; @@ -51,6 +52,8 @@ dbus_bool_t      _dbus_credentials_include                  (DBusCredentials  dbus_pid_t       _dbus_credentials_get_unix_pid             (DBusCredentials    *credentials);  dbus_uid_t       _dbus_credentials_get_unix_uid             (DBusCredentials    *credentials);  const char*      _dbus_credentials_get_windows_sid          (DBusCredentials    *credentials); +void *           _dbus_credentials_get_adt_audit_data       (DBusCredentials    *credentials); +dbus_int32_t     _dbus_credentials_get_adt_audit_data_size  (DBusCredentials    *credentials);  dbus_bool_t      _dbus_credentials_are_superset             (DBusCredentials    *credentials,                                                               DBusCredentials    *possible_subset);  dbus_bool_t      _dbus_credentials_are_empty                (DBusCredentials    *credentials); diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h index 58677dcf..814deae0 100644 --- a/dbus/dbus-protocol.h +++ b/dbus/dbus-protocol.h @@ -411,6 +411,8 @@ extern "C" {  #define DBUS_ERROR_INVALID_FILE_CONTENT       "org.freedesktop.DBus.Error.InvalidFileContent"  /** Asked for SELinux security context and it wasn't available. */  #define DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN    "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown" +/** Asked for ADT audit data and it wasn't available. */ +#define DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN     "org.freedesktop.DBus.Error.AdtAuditDataUnknown"  /** There's already an object with the requested object path. */  #define DBUS_ERROR_OBJECT_PATH_IN_USE         "org.freedesktop.DBus.Error.ObjectPathInUse" diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index a66d0710..64d925d9 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -71,6 +71,10 @@  #include <ucred.h>  #endif +#ifdef HAVE_ADT +#include <bsm/adt.h> +#endif +  #ifndef O_BINARY  #define O_BINARY 0  #endif @@ -1260,6 +1264,37 @@ _dbus_read_credentials_socket  (int              client_fd,        {          pid_read = ucred_getpid (ucred);          uid_read = ucred_geteuid (ucred); +#ifdef HAVE_ADT +        /* generate audit session data based on socket ucred */ +        adt_session_data_t *adth = NULL; +        adt_export_data_t *data = NULL; +        size_t size = 0; +        if (adt_start_session (&adth, NULL, 0) || (adth == NULL)) +          { +            _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno)); +          } +        else  +          { +            if (adt_set_from_ucred (adth, ucred, ADT_NEW))  +              { +                _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno)); +              } +            else +              { +                size = adt_export_session_data (adth, &data); +                if (size <= 0) +                  { +                    _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno)); +                  } +                else +                  { +                    _dbus_credentials_add_adt_audit_data (credentials, data, size); +                    free (data); +                  } +              } +            (void) adt_end_session (adth); +          } +#endif /* HAVE_ADT */        }      else        { diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index 1e1fc97d..90291980 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -1262,6 +1262,40 @@ _dbus_transport_get_unix_process_id (DBusTransport *transport,  }  /** + * See dbus_connection_get_adt_audit_session_data(). + * + * @param transport the transport + * @param data return location for the ADT audit data  + * @param data_size return length of audit data + * @returns #TRUE if audit data is filled in with a valid ucred + */ +dbus_bool_t +_dbus_transport_get_adt_audit_session_data (DBusTransport      *transport, +                                            void              **data, +                                            int                *data_size) +{ +  DBusCredentials *auth_identity; + +  *data = NULL; +  *data_size = 0; +   +  if (!transport->authenticated) +    return FALSE; +   +  auth_identity = _dbus_auth_get_identity (transport->auth); + +  if (_dbus_credentials_include (auth_identity, +                                 DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID)) +    { +      *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity); +      *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity); +      return TRUE; +    } +  else +    return FALSE; +} + +/**   * See dbus_connection_set_unix_user_function().   *   * @param transport the transport diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h index 9a9e5532..691763ca 100644 --- a/dbus/dbus-transport.h +++ b/dbus/dbus-transport.h @@ -64,6 +64,9 @@ dbus_bool_t        _dbus_transport_get_unix_user          (DBusTransport                                                             unsigned long              *uid);  dbus_bool_t        _dbus_transport_get_unix_process_id     (DBusTransport              *transport,                                                             unsigned long              *pid); +dbus_bool_t        _dbus_transport_get_adt_audit_session_data (DBusTransport              *transport, +                                                               void                      **data, +                                                               int                        *data_size);  void               _dbus_transport_set_unix_user_function (DBusTransport              *transport,                                                             DBusAllowUnixUserFunction   function,                                                             void                       *data, | 
