Commit ab1eb1fd authored by Colin Walters's avatar Colin Walters

Bug 15740: Solaris/ADT auditing support (simon zheng)

	* bus/driver.c: Add GetAdtAuditSessionData method
	which returns audit data for a connection.
	* configure.in: Detect ADT auditing support
	* dbus/dbus-auth.c: Read ADT auditing creds.
	* dbus/dbus-connection.c: Implement
	dbus_connection_get_adt_audit_session_data.
	* dbus/dbus-connection.h: Export it.
	* dbus/dbus-credentials.c: Add support for
	gathering adt_audit_data and retrieving it
	via _dbus_credentials_get_adt_audit_data.
	* dbus/dbus-credentials.h: Add
	DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID.
	* dbus/dbus-protocol.h: New error
	DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN.
	* dbus/dbus-sysdeps.c: Support for reading
	audit credentials via ADT API.
	* dbus/dbus-transport.c: New function
	_dbus_transport_get_adt_audit_session_data
	to retrieve credentials.
	* dbus/dbus-transport.h: Export it.
parent 81c32a52
......@@ -1272,6 +1272,81 @@ bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection,
return FALSE;
}
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,
......@@ -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,
......
......@@ -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)
......
......@@ -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;
......
......@@ -4985,6 +4985,40 @@ dbus_connection_get_unix_process_id (DBusConnection *connection,
return result;
}
/**
* 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
......
......@@ -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,
......
......@@ -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);
}
}
......@@ -187,6 +192,31 @@ _dbus_credentials_add_windows_sid (DBusCredentials *credentials,
return TRUE;
}
/**
* 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.
*
......@@ -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");
......@@ -251,6 +283,32 @@ _dbus_credentials_get_windows_sid (DBusCredentials *credentials)
return credentials->windows_sid;
}
/**
* 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;
}
/**
......@@ -321,6 +384,9 @@ _dbus_credentials_add_credentials (DBusCredentials *credentials,
_dbus_credentials_add_credential (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;
}
/**
......
......@@ -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);
......
......@@ -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"
......
......@@ -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
{
......
......@@ -1261,6 +1261,40 @@ _dbus_transport_get_unix_process_id (DBusTransport *transport,
return FALSE;
}
/**
* 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().
*
......
......@@ -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,
......
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