core: merge branch bg/audit-bgo749364

Log all the relevant changes to system configuration and state to the
Linux audit subsystem through libaudit (if enabled at build time) and
to the logging system.

https://bugzilla.gnome.org/show_bug.cgi?id=749364
This commit is contained in:
Beniamino Galvani 2015-08-04 09:35:29 +02:00
commit 7c38b78463
23 changed files with 725 additions and 68 deletions

View file

@ -272,8 +272,6 @@ dnl
dnl Checks for dbus-glib
dnl
PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.1 dbus-glib-1 >= 0.94)
AC_SUBST(DBUS_CFLAGS)
AC_SUBST(DBUS_LIBS)
AC_CHECK_LIB([dbus-glib-1], [dbus_g_method_invocation_get_g_connection], ac_have_gmi_get_con="1", ac_have_gmi_get_con="0")
AC_DEFINE_UNQUOTED(HAVE_DBUS_GLIB_GMI_GET_CONNECTION, $ac_have_gmi_get_con, [Define if you have a dbus-glib with dbus_g_method_invocation_get_g_connection()])
@ -305,8 +303,6 @@ AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)
PKG_CHECK_MODULES(GUDEV, gudev-1.0 >= 165)
AC_SUBST(GUDEV_CFLAGS)
AC_SUBST(GUDEV_LIBS)
GOBJECT_INTROSPECTION_CHECK([0.9.6])
@ -318,8 +314,6 @@ if (test "${enable_qt}" = "yes"); then
if test x"$have_qt" = x"no"; then
AC_MSG_ERROR(Qt development headers are required)
fi
AC_SUBST(QT_CFLAGS)
AC_SUBST(QT_LIBS)
# Check for moc-qt4 and if not found then moc
QT4_BINDIR=`$PKG_CONFIG QtCore --variable moc_location`
AC_CHECK_PROGS(MOC, [moc-qt4 moc],, [$QT4_BINDIR:$PATH])
@ -393,8 +387,6 @@ if test "$with_systemd_journal" != "no"; then
fi
fi
if test "$have_systemd_journal" = "yes"; then
AC_SUBST(SYSTEMD_JOURNAL_CFLAGS)
AC_SUBST(SYSTEMD_JOURNAL_LIBS)
AC_DEFINE([SYSTEMD_JOURNAL], 1, [Define to 1 if libsystemd-journald is available])
else
AC_DEFINE([SYSTEMD_JOURNAL], 0, [Define to 1 if libsystemd-journald is available])
@ -450,8 +442,6 @@ if test "$use_systemd_logind" = "yes" -a "$have_systemd_logind" = "no"; then
AC_MSG_ERROR([You must have libsystemd installed to build with systemd-logind support.])
fi
if test "$have_systemd_logind" = "yes"; then
AC_SUBST(SYSTEMD_LOGIN_CFLAGS)
AC_SUBST(SYSTEMD_LOGIN_LIBS)
AC_DEFINE([SESSION_TRACKING_SYSTEMD], 1, [Define to 1 if libsystemd-login is available])
session_tracking="$session_tracking, systemd-logind"
fi
@ -503,12 +493,25 @@ if test "$have_selinux" = "yes"; then
else
AC_DEFINE(HAVE_SELINUX, 0, [Define if you have SELinux support])
fi
AM_CONDITIONAL(HAVE_SELINUX, test "${have_selinux}" = "yes")
# libaudit support
AC_ARG_WITH(libaudit, AS_HELP_STRING([--with-libaudit=yes|no|auto], [Build with audit daemon support (default: auto)]),,[with_libaudit=auto])
if test "$with_libaudit" = "yes" -o "$with_libaudit" = "auto"; then
PKG_CHECK_MODULES(LIBAUDIT, audit, [have_libaudit=yes], [have_libaudit=no])
else
have_libaudit=no
fi
if test "$with_libaudit" = "yes" -a "$have_libaudit" = "no"; then
AC_MSG_ERROR([You must have libaudit installed to build --with-libaudit=yes.])
fi
if test "$have_libaudit" = "yes"; then
AC_DEFINE(HAVE_LIBAUDIT, 1, [Define if you have libaudit support])
else
AC_DEFINE(HAVE_LIBAUDIT, 0, [Define if you have libaudit support])
fi
# libnl support for the linux platform
PKG_CHECK_MODULES(LIBNL, libnl-3.0 >= 3.2.8 libnl-route-3.0 libnl-genl-3.0)
AC_SUBST(LIBNL_CFLAGS)
AC_SUBST(LIBNL_LIBS)
AC_CHECK_LIB([nl-route-3], [rtnl_link_inet6_get_addr_gen_mode],
ac_have_addr_gen_mode="1",
@ -542,8 +545,6 @@ AC_DEFINE_UNQUOTED(HAVE_LIBNL_INET6_TOKEN,
# uuid library
PKG_CHECK_MODULES(UUID, uuid)
AC_SUBST(UUID_CFLAGS)
AC_SUBST(UUID_LIBS)
dnl Checks for readline library - used by nmcli
AX_LIB_READLINE
@ -556,9 +557,6 @@ if (test "${enable_teamdctl}" = "yes"); then
if test x"$have_teamdctl" = x"no"; then
AC_MSG_ERROR(Teamd control is required)
fi
AC_SUBST(LIBTEAMDCTL_CFLAGS)
AC_SUBST(LIBTEAMDCTL_LIBS)
# temporary bug workaround
LIBTEAMDCTL_CFLAGS=`echo $LIBTEAMDCTL_CFLAGS | sed -e 's:/teamdctl.h::'`
AC_DEFINE(WITH_TEAMDCTL, 1, [Define if you have Teamd control support])
@ -596,9 +594,6 @@ if (test "${enable_polkit_agent}" = "yes"); then
if test x"$have_pk_agent" = x"no"; then
AC_MSG_ERROR(Polkit agent is required)
fi
AC_SUBST(POLKIT_CFLAGS)
AC_SUBST(POLKIT_LIBS)
AC_DEFINE(WITH_POLKIT_AGENT, 1, [Define if you have polkit agent])
else
AC_DEFINE(WITH_POLKIT_AGENT, 0, [Define if you have polkit agent])
@ -627,15 +622,11 @@ if test x"$ac_crypto" = xnss; then
AC_MSG_ERROR([No usable NSS found])
fi
AC_SUBST(NSS_CFLAGS)
AC_SUBST(NSS_LIBS)
AC_DEFINE(HAVE_NSS, 1, [Define if you have NSS])
with_nss=yes
elif test x"$ac_crypto" = xgnutls; then
PKG_CHECK_MODULES(GNUTLS, [gnutls >= 2.12])
AC_DEFINE(HAVE_GNUTLS, 1, [Define if you have libgnutls])
AC_SUBST(GNUTLS_CFLAGS)
AC_SUBST(GNUTLS_LIBS)
with_gnutls=yes
else
AC_MSG_ERROR([Please choose either 'nss' or 'gnutls' for certificate and crypto operations])
@ -702,8 +693,6 @@ if (test "${with_modem_manager_1}" != "no"); then
[mm-glib >= 0.7.991],
[have_libmm_glib=yes],
[have_libmm_glib=no])
AC_SUBST(MM_GLIB_CFLAGS)
AC_SUBST(MM_GLIB_LIBS)
if (test "${have_libmm_glib}" = "no"); then
if (test "${with_modem_manager_1}" = "yes"); then
@ -868,8 +857,6 @@ if (test "${enable_concheck}" = "yes"); then
if test x"$with_libsoup" = x"no"; then
AC_MSG_ERROR(Connectivity checking requires libsoup)
fi
AC_SUBST(LIBSOUP_CFLAGS)
AC_SUBST(LIBSOUP_LIBS)
AC_DEFINE(WITH_CONCHECK, 1, [Define if you want connectivity checking support])
else
AC_DEFINE(WITH_CONCHECK, 0, [Define if you want connectivity checking support])
@ -1137,6 +1124,7 @@ echo " polkit agent: ${enable_polkit_agent}"
echo " selinux: $have_selinux"
echo " systemd-journald: $have_systemd_journal (logging.backend: ${nm_config_logging_backend_default})"
echo " hostname persist: ${hostname_persist}"
echo " libaudit: $have_libaudit"
echo
echo "Features:"

View file

@ -23,3 +23,4 @@
[logging]
#level=DEBUG
#audit=yes

View file

@ -138,6 +138,7 @@ BuildRequires: ppp-devel >= 2.4.5
BuildRequires: nss-devel >= 3.11.7
BuildRequires: dhclient
BuildRequires: readline-devel
BuildRequires: audit-libs-devel
%if %{regen_docs}
BuildRequires: gtk-doc
%endif
@ -379,6 +380,7 @@ by nm-connection-editor and nm-applet in a non-graphical environment.
--with-crypto=nss \
--enable-more-warnings=error \
--enable-ppp=yes \
--with-libaudit=yes \
%if 0%{?with_modem_manager_1}
--with-modem-manager-1=yes \
%else

View file

@ -11,7 +11,7 @@ ExecStart=@sbindir@/NetworkManager --no-daemon
Restart=on-failure
# NM doesn't want systemd to kill its children for it
KillMode=process
CapabilityBoundingSet=CAP_NET_ADMIN CAP_DAC_OVERRIDE CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_MODULE
CapabilityBoundingSet=CAP_NET_ADMIN CAP_DAC_OVERRIDE CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_MODULE CAP_AUDIT_WRITE
ProtectSystem=true
ProtectHome=read-only

View file

@ -135,6 +135,7 @@ char ** _nm_utils_slist_to_strv (GSList *slist, gboolean deep_copy);
GPtrArray * _nm_utils_strv_to_ptrarray (char **strv);
char ** _nm_utils_ptrarray_to_strv (GPtrArray *ptrarray);
gboolean _nm_utils_strv_equal (char **strv1, char **strv2);
gboolean _nm_utils_check_file (const char *filename,
gint64 check_owner,

View file

@ -845,6 +845,30 @@ _nm_utils_ptrarray_to_strv (GPtrArray *ptrarray)
return strv;
}
/**
* _nm_utils_strv_equal:
* @strv1: a string array
* @strv2: a string array
*
* Compare NULL-terminated string arrays for equality.
*
* Returns: %TRUE if the arrays are equal, %FALSE otherwise.
**/
gboolean
_nm_utils_strv_equal (char **strv1, char **strv2)
{
if (strv1 == strv2)
return TRUE;
if (!strv1 || !strv2)
return FALSE;
for ( ; *strv1 && *strv2 && !strcmp (*strv1, *strv2); strv1++, strv2++)
;
return !*strv1 && !*strv2;
}
/**
* _nm_utils_strsplit_set:
* @str: string to split

View file

@ -414,7 +414,7 @@ unmanaged-devices=mac:00:22:68:1c:59:b1;mac:00:1E:65:30:D1:C4;interface-name:eth
WIFI_SCAN, IP4, IP6, AUTOIP4, DNS, VPN, SHARING, SUPPLICANT,
AGENTS, SETTINGS, SUSPEND, CORE, DEVICE, OLPC, WIMAX,
INFINIBAND, FIREWALL, ADSL, BOND, VLAN, BRIDGE, DBUS_PROPS,
TEAM, CONCHECK, DCB, DISPATCH.</para>
TEAM, CONCHECK, DCB, DISPATCH, AUDIT.</para>
<para>In addition, these special domains can be used: NONE,
ALL, DEFAULT, DHCP, IP.</para>
<para>You can specify per-domain log level overrides by
@ -459,6 +459,7 @@ unmanaged-devices=mac:00:22:68:1c:59:b1;mac:00:1E:65:30:D1:C4;interface-name:eth
<member>CONCHECK : Connectivity check</member>
<member>DCB : Data Center Bridging (DCB) operations</member>
<member>DISPATCH : Dispatcher scripts</member>
<member>AUDIT : Audit records</member>
<member> </member>
<member>NONE : when given by itself logging is disabled</member>
<member>ALL : all log domains</member>
@ -484,6 +485,15 @@ unmanaged-devices=mac:00:22:68:1c:59:b1;mac:00:1E:65:30:D1:C4;interface-name:eth
Otherwise, the default is "<literal>@NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@</literal>".
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>audit</varname></term>
<listitem><para>Whether the audit records are delivered to
auditd, the audit daemon. If <literal>false</literal>, audit
records will be sent only to the NetworkManager logging
system. If set to <literal>true</literal>, they will be also
sent to auditd. The default value is <literal>false</literal>.
</para></listitem>
</varlistentry>
</variablelist>
</para>
</refsect1>

View file

@ -300,6 +300,8 @@ nm_sources = \
nm-activation-request.h \
nm-active-connection.c \
nm-active-connection.h \
nm-audit-manager.c \
nm-audit-manager.h \
nm-bus-manager.c \
nm-bus-manager.h \
nm-config.c \
@ -418,6 +420,7 @@ AM_CPPFLAGS += \
$(LIBNDP_CFLAGS) \
$(LIBSOUP_CFLAGS) \
$(SELINUX_CFLAGS) \
$(LIBAUDIT_CFLAGS) \
$(SYSTEMD_LOGIN_CFLAGS) \
$(SYSTEMD_JOURNAL_CFLAGS) \
$(SYSTEMD_NM_CFLAGS) \
@ -459,16 +462,14 @@ libNetworkManager_la_LIBADD = \
$(SYSTEMD_JOURNAL_LIBS) \
$(LIBNDP_LIBS) \
$(LIBDL) \
$(LIBM)
$(LIBM) \
$(SELINUX_LIBS) \
$(LIBAUDIT_LIBS)
if WITH_LIBSOUP
libNetworkManager_la_LIBADD += $(LIBSOUP_LIBS)
endif
if HAVE_SELINUX
libNetworkManager_la_LIBADD += $(SELINUX_LIBS)
endif
NetworkManager_LDFLAGS = -rdynamic
######################

View file

@ -66,6 +66,7 @@
#include "nm-default-route-manager.h"
#include "nm-route-manager.h"
#include "sd-ipv4ll.h"
#include "nm-audit-manager.h"
#include "nm-device-logging.h"
_LOG_DECLARE_SELF (NMDevice);
@ -6177,6 +6178,7 @@ delete_on_deactivate_check_and_schedule (NMDevice *self, int ifindex)
static void
disconnect_cb (NMDevice *self,
DBusGMethodInvocation *context,
NMAuthSubject *subject,
GError *error,
gpointer user_data)
{
@ -6185,6 +6187,7 @@ disconnect_cb (NMDevice *self,
if (error) {
dbus_g_method_return_error (context, error);
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DISCONNECT, self, FALSE, subject, error->message);
return;
}
@ -6194,6 +6197,7 @@ disconnect_cb (NMDevice *self,
NM_DEVICE_ERROR_NOT_ACTIVE,
"Device is not active");
dbus_g_method_return_error (context, local);
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DISCONNECT, self, FALSE, subject, local->message);
g_error_free (local);
} else {
nm_device_set_autoconnect (self, FALSE);
@ -6202,6 +6206,7 @@ disconnect_cb (NMDevice *self,
NM_DEVICE_STATE_DEACTIVATING,
NM_DEVICE_STATE_REASON_USER_REQUESTED);
dbus_g_method_return (context);
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DISCONNECT, self, TRUE, subject, NULL);
}
}
@ -6245,17 +6250,20 @@ impl_device_disconnect (NMDevice *self, DBusGMethodInvocation *context)
static void
delete_cb (NMDevice *self,
DBusGMethodInvocation *context,
NMAuthSubject *subject,
GError *error,
gpointer user_data)
{
if (error) {
dbus_g_method_return_error (context, error);
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DELETE, self, FALSE, subject, error->message);
return;
}
/* Authorized */
nm_platform_link_delete (NM_PLATFORM_GET, nm_device_get_ifindex (self));
dbus_g_method_return (context);
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DELETE, self, TRUE, subject, NULL);
}
static void

View file

@ -311,6 +311,7 @@ typedef struct {
typedef void (*NMDeviceAuthRequestFunc) (NMDevice *device,
DBusGMethodInvocation *context,
NMAuthSubject *subject,
GError *error,
gpointer user_data);

View file

@ -1057,6 +1057,7 @@ impl_device_get_all_access_points (NMDeviceWifi *self,
static void
request_scan_cb (NMDevice *device,
DBusGMethodInvocation *context,
NMAuthSubject *subject,
GError *error,
gpointer user_data)
{

371
src/nm-audit-manager.c Normal file
View file

@ -0,0 +1,371 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager audit support
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2015 Red Hat, Inc.
*/
#include "config.h"
#include <errno.h>
#include <string.h>
#if HAVE_LIBAUDIT
#include <libaudit.h>
#endif
#include "gsystem-local-alloc.h"
#include "nm-audit-manager.h"
#include "nm-glib.h"
#include "nm-auth-subject.h"
#include "nm-config.h"
#include "nm-logging.h"
#include "nm-macros-internal.h"
#define AUDIT_LOG_LEVEL LOGL_INFO
typedef enum {
BACKEND_LOG = (1 << 0),
BACKEND_AUDITD = (1 << 1),
_BACKEND_LAST,
BACKEND_ALL = ((_BACKEND_LAST - 1) << 1) - 1,
} AuditBackend;
typedef struct {
const char *name;
GValue value;
gboolean need_encoding;
AuditBackend backends;
} AuditField;
typedef struct {
#if HAVE_LIBAUDIT
NMConfig *config;
int auditd_fd;
#endif
} NMAuditManagerPrivate;
#define NM_AUDIT_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AUDIT_MANAGER, NMAuditManagerPrivate))
G_DEFINE_TYPE (NMAuditManager, nm_audit_manager, G_TYPE_OBJECT)
NM_DEFINE_SINGLETON_GETTER (NMAuditManager, nm_audit_manager_get, NM_TYPE_AUDIT_MANAGER);
static void
_audit_field_init_string (AuditField *field, const char *name, const char *str,
gboolean need_encoding, AuditBackend backends)
{
field->name = name;
field->need_encoding = need_encoding;
field->backends = backends;
g_value_init (&field->value, G_TYPE_STRING);
g_value_set_static_string (&field->value, str);
}
static void
_audit_field_init_uint (AuditField *field, const char *name, uint val,
AuditBackend backends)
{
field->name = name;
field->backends = backends;
g_value_init (&field->value, G_TYPE_UINT);
g_value_set_uint (&field->value, val);
}
static char *
build_message (GPtrArray *fields, AuditBackend backend)
{
GString *string;
AuditField *field;
gboolean first = TRUE;
guint i;
string = g_string_new (NULL);
for (i = 0; i < fields->len; i++) {
field = fields->pdata[i];
if (!NM_FLAGS_HAS (field->backends, backend))
continue;
if (first)
first = FALSE;
else
g_string_append_c (string, ' ');
if (G_VALUE_HOLDS_STRING (&field->value)) {
const char *str = g_value_get_string (&field->value);
#if HAVE_LIBAUDIT
if (backend == BACKEND_AUDITD) {
if (field->need_encoding) {
char *value;
value = audit_encode_nv_string (field->name, str, 0);
g_string_append (string, value);
g_free (value);
} else
g_string_append_printf (string, "%s=%s", field->name, str);
continue;
}
#endif /* HAVE_LIBAUDIT */
g_string_append_printf (string, "%s=\"%s\"", field->name, str);
} else if (G_VALUE_HOLDS_UINT (&field->value)) {
g_string_append_printf (string, "%s=%u", field->name,
g_value_get_uint (&field->value));
} else
g_assert_not_reached ();
}
return g_string_free (string, FALSE);
}
static void
nm_audit_log (NMAuditManager *self, GPtrArray *fields, const char *file,
guint line, const char *func, gboolean success)
{
NMAuditManagerPrivate *priv;
char *msg;
g_return_if_fail (NM_IS_AUDIT_MANAGER (self));
priv = NM_AUDIT_MANAGER_GET_PRIVATE (self);
#if HAVE_LIBAUDIT
if (priv->auditd_fd >= 0) {
msg = build_message (fields, BACKEND_AUDITD);
audit_log_user_message (priv->auditd_fd, AUDIT_USYS_CONFIG, msg,
NULL, NULL, NULL, success);
g_free (msg);
}
#endif
if (nm_logging_enabled (AUDIT_LOG_LEVEL, LOGD_AUDIT)) {
msg = build_message (fields, BACKEND_LOG);
_nm_log_impl (file, line, func, AUDIT_LOG_LEVEL, LOGD_AUDIT, 0, "%s", msg);
g_free (msg);
}
}
static void
_audit_log_helper (NMAuditManager *self, GPtrArray *fields, const char *file,
guint line, const char *func, const char *op, gboolean result,
NMAuthSubject *subject, const char *reason)
{
AuditField op_field = { }, pid_field = { }, uid_field = { };
AuditField result_field = { }, reason_field = { };
gulong pid, uid;
_audit_field_init_string (&op_field, "op", op, FALSE, BACKEND_ALL);
g_ptr_array_insert (fields, 0, &op_field);
if (subject && nm_auth_subject_is_unix_process (subject)) {
pid = nm_auth_subject_get_unix_process_pid (subject);
uid = nm_auth_subject_get_unix_process_uid (subject);
if (pid != G_MAXULONG) {
_audit_field_init_uint (&pid_field, "pid", pid, BACKEND_ALL);
g_ptr_array_add (fields, &pid_field);
}
if (uid != G_MAXULONG) {
_audit_field_init_uint (&uid_field, "uid", uid, BACKEND_ALL);
g_ptr_array_add (fields, &uid_field);
}
}
_audit_field_init_string (&result_field, "result", result ? "success" : "fail",
FALSE, BACKEND_ALL);
g_ptr_array_add (fields, &result_field);
if (reason) {
_audit_field_init_string (&reason_field, "reason", reason, FALSE, BACKEND_LOG);
g_ptr_array_add (fields, &reason_field);
}
nm_audit_log (self, fields, file, line, func, result);
}
gboolean
nm_audit_manager_audit_enabled (NMAuditManager *self)
{
#if HAVE_LIBAUDIT
NMAuditManagerPrivate *priv = NM_AUDIT_MANAGER_GET_PRIVATE (self);
if (priv->auditd_fd >= 0)
return TRUE;
#endif
return nm_logging_enabled (AUDIT_LOG_LEVEL, LOGD_AUDIT);
}
void
_nm_audit_manager_log_connection_op (NMAuditManager *self, const char *file, guint line,
const char *func, const char *op, NMConnection *connection,
gboolean result, NMAuthSubject *subject, const char *reason)
{
gs_unref_ptrarray GPtrArray *fields = NULL;
AuditField uuid_field = { }, name_field = { };
g_return_if_fail (op);
g_return_if_fail (connection || !strcmp (op, NM_AUDIT_OP_CONN_ADD));
fields = g_ptr_array_new ();
if (connection) {
_audit_field_init_string (&uuid_field, "uuid", nm_connection_get_uuid (connection),
FALSE, BACKEND_ALL);
g_ptr_array_add (fields, &uuid_field);
_audit_field_init_string (&name_field, "name", nm_connection_get_id (connection),
TRUE, BACKEND_ALL);
g_ptr_array_add (fields, &name_field);
}
_audit_log_helper (self, fields, file, line, func, op, result, subject, reason);
}
void
_nm_audit_manager_log_control_op (NMAuditManager *self, const char *file, guint line,
const char *func, const char *op, const char *arg,
gboolean result, NMAuthSubject *subject,
const char *reason)
{
gs_unref_ptrarray GPtrArray *fields = NULL;
AuditField arg_field = { };
g_return_if_fail (op);
g_return_if_fail (arg);
fields = g_ptr_array_new ();
_audit_field_init_string (&arg_field, "arg", arg, TRUE, BACKEND_ALL);
g_ptr_array_add (fields, &arg_field);
_audit_log_helper (self, fields, file, line, func, op, result, subject, reason);
}
void
_nm_audit_manager_log_device_op (NMAuditManager *self, const char *file, guint line,
const char *func, const char *op, NMDevice *device,
gboolean result, NMAuthSubject *subject,
const char *reason)
{
gs_unref_ptrarray GPtrArray *fields = NULL;
AuditField interface_field = { }, ifindex_field = { };
int ifindex;
g_return_if_fail (op);
g_return_if_fail (device);
fields = g_ptr_array_new ();
_audit_field_init_string (&interface_field, "interface", nm_device_get_ip_iface (device),
TRUE, BACKEND_ALL);
g_ptr_array_add (fields, &interface_field);
ifindex = nm_device_get_ip_ifindex (device);
if (ifindex > 0) {
_audit_field_init_uint (&ifindex_field, "ifindex", ifindex, BACKEND_ALL);
g_ptr_array_add (fields, &ifindex_field);
}
_audit_log_helper (self, fields, file, line, func, op, result, subject, reason);
}
#if HAVE_LIBAUDIT
static void
init_auditd (NMAuditManager *self)
{
NMAuditManagerPrivate *priv = NM_AUDIT_MANAGER_GET_PRIVATE (self);
NMConfigData *data = nm_config_get_data (priv->config);
if (nm_config_data_get_value_boolean (data, NM_CONFIG_KEYFILE_GROUP_LOGGING,
NM_CONFIG_KEYFILE_KEY_AUDIT, FALSE)) {
if (priv->auditd_fd < 0) {
priv->auditd_fd = audit_open ();
if (priv->auditd_fd < 0) {
nm_log_err (LOGD_CORE, "failed to open auditd socket: %s",
strerror (errno));
} else
nm_log_dbg (LOGD_CORE, "audit socket created");
}
} else {
if (priv->auditd_fd >= 0) {
audit_close (priv->auditd_fd);
priv->auditd_fd = -1;
nm_log_dbg (LOGD_CORE, "audit socket closed");
}
}
}
static void
config_changed_cb (NMConfig *config,
NMConfigData *config_data,
NMConfigChangeFlags changes,
NMConfigData *old_data,
NMAuditManager *self)
{
if (NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_VALUES))
init_auditd (self);
}
#endif
static void
nm_audit_manager_init (NMAuditManager *self)
{
#if HAVE_LIBAUDIT
NMAuditManagerPrivate *priv = NM_AUDIT_MANAGER_GET_PRIVATE (self);
priv->config = g_object_ref (nm_config_get ());
g_signal_connect (G_OBJECT (priv->config),
NM_CONFIG_SIGNAL_CONFIG_CHANGED,
G_CALLBACK (config_changed_cb),
self);
priv->auditd_fd = -1;
init_auditd (self);
#endif
}
static void
dispose (GObject *object)
{
#if HAVE_LIBAUDIT
NMAuditManager *self = NM_AUDIT_MANAGER (object);
NMAuditManagerPrivate *priv = NM_AUDIT_MANAGER_GET_PRIVATE (self);
if (priv->config) {
g_signal_handlers_disconnect_by_func (priv->config, config_changed_cb, self);
g_clear_object (&priv->config);
}
if (priv->auditd_fd >= 0) {
audit_close (priv->auditd_fd);
priv->auditd_fd = -1;
}
#endif
G_OBJECT_CLASS (nm_audit_manager_parent_class)->dispose (object);
}
static void
nm_audit_manager_class_init (NMAuditManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (klass, sizeof (NMAuditManagerPrivate));
/* virtual methods */
object_class->dispose = dispose;
}

112
src/nm-audit-manager.h Normal file
View file

@ -0,0 +1,112 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager audit support
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2015 Red Hat, Inc.
*/
#ifndef __NM_AUDIT_MANAGER_H__
#define __NM_AUDIT_MANAGER_H__
#include <glib.h>
#include <glib-object.h>
#include "nm-connection.h"
#include "nm-device.h"
#include "nm-types.h"
G_BEGIN_DECLS
#define NM_TYPE_AUDIT_MANAGER (nm_audit_manager_get_type ())
#define NM_AUDIT_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_AUDIT_MANAGER, NMAuditManager))
#define NM_AUDIT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_AUDIT_MANAGER, NMAuditManagerClass))
#define NM_IS_AUDIT_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_AUDIT_MANAGER))
#define NM_IS_AUDIT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_AUDIT_MANAGER))
#define NM_AUDIT_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_AUDIT_MANAGER, NMAuditManagerClass))
struct _NMAuditManager {
GObject parent;
};
typedef struct {
GObjectClass parent;
} NMAuditManagerClass;
#define NM_AUDIT_OP_CONN_ADD "connection-add"
#define NM_AUDIT_OP_CONN_DELETE "connection-delete"
#define NM_AUDIT_OP_CONN_UPDATE "connection-update"
#define NM_AUDIT_OP_CONN_ACTIVATE "connection-activate"
#define NM_AUDIT_OP_CONN_ADD_ACTIVATE "connection-add-activate"
#define NM_AUDIT_OP_CONN_DEACTIVATE "connection-deactivate"
#define NM_AUDIT_OP_CONN_CLEAR_SECRETS "connection-clear-secrets"
#define NM_AUDIT_OP_SLEEP_CONTROL "sleep-control"
#define NM_AUDIT_OP_NET_CONTROL "networking-control"
#define NM_AUDIT_OP_RADIO_CONTROL "radio-control"
#define NM_AUDIT_OP_DEVICE_AUTOCONNECT "device-autoconnect"
#define NM_AUDIT_OP_DEVICE_DISCONNECT "device-disconnect"
#define NM_AUDIT_OP_DEVICE_DELETE "device-delete"
GType nm_audit_manager_get_type (void);
NMAuditManager *nm_audit_manager_get (void);
gboolean nm_audit_manager_audit_enabled (NMAuditManager *self);
#define nm_audit_log_connection_op(op, connection, result, subject, reason) \
G_STMT_START { \
NMAuditManager *_audit = nm_audit_manager_get (); \
\
if (nm_audit_manager_audit_enabled (_audit)) { \
_nm_audit_manager_log_connection_op (_audit, __FILE__, __LINE__, G_STRFUNC, \
(op), (connection), (result), (subject), \
(reason)); \
} \
} G_STMT_END
#define nm_audit_log_control_op(op, arg, result, subject, reason) \
G_STMT_START { \
NMAuditManager *_audit = nm_audit_manager_get (); \
\
if (nm_audit_manager_audit_enabled (_audit)) { \
_nm_audit_manager_log_control_op (_audit, __FILE__, __LINE__, G_STRFUNC, \
(op), (arg), (result), (subject), (reason)); \
} \
} G_STMT_END
#define nm_audit_log_device_op(op, device, result, subject, reason) \
G_STMT_START { \
NMAuditManager *_audit = nm_audit_manager_get (); \
\
if (nm_audit_manager_audit_enabled (_audit)) { \
_nm_audit_manager_log_device_op (_audit, __FILE__, __LINE__, G_STRFUNC, \
(op), (device), (result), (subject), (reason)); \
} \
} G_STMT_END
void _nm_audit_manager_log_connection_op (NMAuditManager *self, const char *file, guint line,
const char *func, const char *op, NMConnection *connection,
gboolean result, NMAuthSubject *subject, const char *reason);
void _nm_audit_manager_log_control_op (NMAuditManager *self, const char *file, guint line,
const char *func, const char *op, const char *arg,
gboolean result, NMAuthSubject *subject, const char *reason);
void _nm_audit_manager_log_device_op (NMAuditManager *self, const char *file, guint line,
const char *func, const char *op, NMDevice *device,
gboolean result, NMAuthSubject *subject, const char *reason);
G_END_DECLS
#endif /* __NM_AUDIT_MANAGER_H__ */

View file

@ -223,6 +223,14 @@ nm_auth_chain_set_data_ulong (NMAuthChain *self,
nm_auth_chain_set_data (self, tag, ptr, g_free);
}
NMAuthSubject *
nm_auth_chain_get_subject (NMAuthChain *self)
{
g_return_val_if_fail (self != NULL, NULL);
return self->subject;
}
NMAuthCallResult
nm_auth_chain_get_result (NMAuthChain *self, const char *permission)
{

View file

@ -92,5 +92,7 @@ gboolean nm_auth_is_subject_in_acl (NMConnection *connection,
NMAuthSubject *subect,
char **out_error_desc);
NMAuthSubject *nm_auth_chain_get_subject (NMAuthChain *self);
#endif /* __NETWORKMANAGER_MANAGER_AUTH_H__ */

View file

@ -65,6 +65,7 @@ G_BEGIN_DECLS
#define NM_CONFIG_KEYFILE_KEY_IFNET_AUTO_REFRESH "auto_refresh"
#define NM_CONFIG_KEYFILE_KEY_IFNET_MANAGED "managed"
#define NM_CONFIG_KEYFILE_KEY_IFUPDOWN_MANAGED "managed"
#define NM_CONFIG_KEYFILE_KEY_AUDIT "audit"
#define NM_CONFIG_KEYFILE_KEYPREFIX_WAS ".was."
#define NM_CONFIG_KEYFILE_KEYPREFIX_SET ".set."

View file

@ -120,6 +120,7 @@ static const LogDesc domain_descs[] = {
{ LOGD_CONCHECK, "CONCHECK" },
{ LOGD_DCB, "DCB" },
{ LOGD_DISPATCH, "DISPATCH" },
{ LOGD_AUDIT, "AUDIT" },
{ 0, NULL }
};

View file

@ -67,6 +67,7 @@ typedef enum { /*< skip >*/
LOGD_CONCHECK = (1LL << 31),
LOGD_DCB = (1LL << 32), /* Data Center Bridging */
LOGD_DISPATCH = (1LL << 33),
LOGD_AUDIT = (1LL << 34),
__LOGD_MAX,
LOGD_ALL = ((__LOGD_MAX - 1LL) << 1) - 1LL,

View file

@ -57,6 +57,7 @@
#include "nm-activation-request.h"
#include "nm-core-internal.h"
#include "nm-config.h"
#include "nm-audit-manager.h"
static gboolean impl_manager_get_devices (NMManager *manager,
GPtrArray **devices,
@ -1357,6 +1358,7 @@ device_auth_done_cb (NMAuthChain *chain,
NMDevice *device;
const char *permission;
NMDeviceAuthRequestFunc callback;
NMAuthSubject *subject;
g_assert (context);
@ -1370,6 +1372,7 @@ device_auth_done_cb (NMAuthChain *chain,
g_assert (device);
result = nm_auth_chain_get_result (chain, permission);
subject = nm_auth_chain_get_subject (chain);
if (auth_error) {
/* translate the auth error into a manager permission denied error */
@ -1390,6 +1393,7 @@ device_auth_done_cb (NMAuthChain *chain,
callback (device,
context,
subject,
error,
nm_auth_chain_get_data (chain, "user-data"));
@ -1450,9 +1454,10 @@ device_auth_request_cb (NMDevice *device,
nm_auth_chain_add_call (chain, permission, allow_interaction);
done:
g_clear_object (&subject);
if (error)
callback (device, context, error, user_data);
callback (device, context, subject, error, user_data);
g_clear_object (&subject);
g_clear_error (&error);
}
@ -3089,10 +3094,17 @@ _activation_auth_done (NMActiveConnection *active,
NMManager *self = user_data1;
DBusGMethodInvocation *context = user_data2;
GError *error = NULL;
NMAuthSubject *subject;
NMConnection *connection;
subject = nm_active_connection_get_subject (active);
connection = nm_active_connection_get_connection (active);
if (success) {
if (_internal_activate_generic (self, active, &error)) {
dbus_g_method_return (context, nm_exported_object_get_path (NM_EXPORTED_OBJECT (active)));
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, TRUE,
subject, NULL);
g_object_unref (active);
return;
}
@ -3104,7 +3116,10 @@ _activation_auth_done (NMActiveConnection *active,
g_assert (error);
dbus_g_method_return_error (context, error);
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, FALSE,
subject, error->message);
_internal_activation_failed (self, active, error->message);
g_object_unref (active);
g_error_free (error);
}
@ -3119,7 +3134,7 @@ impl_manager_activate_connection (NMManager *self,
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
NMActiveConnection *active = NULL;
NMAuthSubject *subject = NULL;
NMConnection *connection;
NMConnection *connection = NULL;
NMDevice *device = NULL;
gboolean is_vpn = FALSE;
GError *error = NULL;
@ -3211,6 +3226,10 @@ impl_manager_activate_connection (NMManager *self,
return;
error:
if (connection) {
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, FALSE,
subject, error->message);
}
g_clear_object (&active);
g_clear_object (&subject);
@ -3231,6 +3250,7 @@ activation_add_done (NMSettings *self,
NMSettingsConnection *new_connection,
GError *error,
DBusGMethodInvocation *context,
NMAuthSubject *subject,
gpointer user_data)
{
AddAndActivateInfo *info = user_data;
@ -3246,6 +3266,11 @@ activation_add_done (NMSettings *self,
dbus_g_method_return (context,
nm_connection_get_path (NM_CONNECTION (new_connection)),
nm_exported_object_get_path (NM_EXPORTED_OBJECT (info->active)));
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE,
nm_active_connection_get_connection (info->active),
TRUE,
nm_active_connection_get_subject (info->active),
NULL);
goto done;
}
error = local;
@ -3255,6 +3280,11 @@ activation_add_done (NMSettings *self,
_internal_activation_failed (info->manager, info->active, error->message);
nm_settings_connection_delete (new_connection, NULL, NULL);
dbus_g_method_return_error (context, error);
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE,
nm_active_connection_get_connection (info->active),
FALSE,
nm_active_connection_get_subject (info->active),
error->message);
g_clear_error (&local);
done:
@ -3293,6 +3323,11 @@ _add_and_activate_auth_done (NMActiveConnection *active,
NM_MANAGER_ERROR_PERMISSION_DENIED,
error_desc);
dbus_g_method_return_error (context, error);
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE,
nm_active_connection_get_connection (active),
FALSE,
nm_active_connection_get_subject (active),
error->message);
g_error_free (error);
}
@ -3399,6 +3434,7 @@ impl_manager_add_and_activate_connection (NMManager *self,
return;
error:
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE, connection, FALSE, subject, error->message);
g_clear_object (&connection);
g_slist_free (all_connections);
g_clear_object (&subject);
@ -3462,12 +3498,16 @@ deactivate_net_auth_done_cb (NMAuthChain *chain,
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GError *error = NULL;
NMAuthCallResult result;
NMActiveConnection *active;
char *path;
g_assert (context);
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
path = nm_auth_chain_get_data (chain, "path");
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL);
active = active_connection_get_by_path (self, path);
if (auth_error) {
nm_log_dbg (LOGD_CORE, "Disconnect request failed: %s", auth_error->message);
@ -3482,7 +3522,7 @@ deactivate_net_auth_done_cb (NMAuthChain *chain,
} else {
/* success; deactivation allowed */
if (!nm_manager_deactivate_connection (self,
nm_auth_chain_get_data (chain, "path"),
path,
NM_DEVICE_STATE_REASON_USER_REQUESTED,
&error))
g_assert (error);
@ -3493,6 +3533,14 @@ deactivate_net_auth_done_cb (NMAuthChain *chain,
else
dbus_g_method_return (context);
if (active) {
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DEACTIVATE,
nm_active_connection_get_connection (active),
!error,
nm_auth_chain_get_subject (chain),
error ? error->message : NULL);
}
g_clear_error (&error);
nm_auth_chain_unref (chain);
}
@ -3561,9 +3609,14 @@ impl_manager_deactivate_connection (NMManager *self,
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE);
done:
g_clear_object (&subject);
if (error)
if (error) {
dbus_g_method_return_error (context, error);
if (connection) {
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DEACTIVATE, connection, FALSE,
subject, error->message);
}
}
g_clear_object (&subject);
g_clear_error (&error);
}
@ -3725,6 +3778,7 @@ impl_manager_sleep (NMManager *self,
{
NMManagerPrivate *priv;
GError *error = NULL;
gs_unref_object NMAuthSubject *subject = NULL;
#if 0
NMAuthChain *chain;
const char *error_desc = NULL;
@ -3733,12 +3787,15 @@ impl_manager_sleep (NMManager *self,
g_return_if_fail (NM_IS_MANAGER (self));
priv = NM_MANAGER_GET_PRIVATE (self);
subject = nm_auth_subject_new_unix_process_from_context (context);
if (priv->sleeping == do_sleep) {
error = g_error_new (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE,
"Already %s", do_sleep ? "asleep" : "awake");
dbus_g_method_return_error (context, error);
nm_audit_log_control_op (NM_AUDIT_OP_SLEEP_CONTROL, do_sleep ? "on" : "off", FALSE, subject,
error->message);
g_error_free (error);
return;
}
@ -3752,6 +3809,7 @@ impl_manager_sleep (NMManager *self,
* D-Bus permissions to restrict the call to root.
*/
_internal_sleep (self, do_sleep);
nm_audit_log_control_op (NM_AUDIT_OP_SLEEP_CONTROL, do_sleep ? "on" : "off", TRUE, subject, NULL);
dbus_g_method_return (context);
return;
@ -3828,10 +3886,13 @@ enable_net_done_cb (NMAuthChain *chain,
GError *ret_error = NULL;
NMAuthCallResult result;
gboolean enable;
NMAuthSubject *subject;
g_assert (context);
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
enable = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "enable"));
subject = nm_auth_chain_get_subject (chain);
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK);
if (error) {
@ -3846,13 +3907,16 @@ enable_net_done_cb (NMAuthChain *chain,
"Not authorized to enable/disable networking");
} else {
/* Auth success */
enable = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "enable"));
_internal_enable (self, enable);
dbus_g_method_return (context);
nm_audit_log_control_op (NM_AUDIT_OP_NET_CONTROL, enable ? "on" : "off", TRUE,
subject, NULL);
}
if (ret_error) {
dbus_g_method_return_error (context, ret_error);
nm_audit_log_control_op (NM_AUDIT_OP_NET_CONTROL, enable ? "on" : "off", FALSE,
subject, ret_error->message);
g_error_free (ret_error);
}
@ -4360,9 +4424,11 @@ prop_set_auth_done_cb (NMAuthChain *chain,
DBusConnection *connection;
NMAuthCallResult result;
DBusMessage *reply = NULL, *message;
const char *permission, *prop;
const char *permission, *prop, *audit_op;
GObject *obj;
gboolean set_enabled = TRUE;
NMAuthSubject *subject;
gs_free char *prop_value = NULL;
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
@ -4371,15 +4437,21 @@ prop_set_auth_done_cb (NMAuthChain *chain,
prop = nm_auth_chain_get_data (chain, "prop");
set_enabled = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "enabled"));
obj = nm_auth_chain_get_data (chain, "object");
audit_op = nm_auth_chain_get_data (chain, "audit-op");
prop_value = g_strdup_printf ("%s:%d", prop, set_enabled);
result = nm_auth_chain_get_result (chain, permission);
subject = nm_auth_chain_get_subject (chain);
if (error || (result != NM_AUTH_CALL_RESULT_YES)) {
reply = dbus_message_new_error (message,
NM_IS_DEVICE (obj) ? DEV_PERM_DENIED_ERROR : NM_PERM_DENIED_ERROR,
"Not authorized to perform this operation");
nm_audit_log_control_op (audit_op, prop_value, FALSE, subject, error ? error->message : NULL);
} else {
g_object_set (obj, prop, set_enabled, NULL);
reply = dbus_message_new_method_return (message);
nm_audit_log_control_op (audit_op, prop_value, TRUE, subject, NULL);
}
g_assert (reply);
@ -4408,6 +4480,7 @@ prop_filter (DBusConnection *connection,
NMAuthSubject *subject = NULL;
NMAuthChain *chain;
GObject *obj;
const char *audit_op = NULL;
/* The sole purpose of this function is to validate property accesses
* on the NMManager object since dbus-glib doesn't yet give us this
@ -4436,15 +4509,19 @@ prop_filter (DBusConnection *connection,
if (!strcmp (propname, "WirelessEnabled")) {
glib_propname = NM_MANAGER_WIRELESS_ENABLED;
permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI;
audit_op = NM_AUDIT_OP_RADIO_CONTROL;
} else if (!strcmp (propname, "WwanEnabled")) {
glib_propname = NM_MANAGER_WWAN_ENABLED;
permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN;
audit_op = NM_AUDIT_OP_RADIO_CONTROL;
} else if (!strcmp (propname, "WimaxEnabled")) {
glib_propname = NM_MANAGER_WIMAX_ENABLED;
permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX;
audit_op = NM_AUDIT_OP_RADIO_CONTROL;
} else if (!strcmp (propname, "Autoconnect")) {
glib_propname = NM_DEVICE_AUTOCONNECT;
permission = NM_AUTH_PERMISSION_NETWORK_CONTROL;
audit_op = NM_AUDIT_OP_DEVICE_AUTOCONNECT;
} else
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@ -4487,6 +4564,7 @@ prop_filter (DBusConnection *connection,
nm_auth_chain_set_data (chain, "message", dbus_message_ref (message), (GDestroyNotify) dbus_message_unref);
nm_auth_chain_set_data (chain, "connection", dbus_connection_ref (connection), (GDestroyNotify) dbus_connection_unref);
nm_auth_chain_set_data (chain, "object", g_object_ref (obj), (GDestroyNotify) g_object_unref);
nm_auth_chain_set_data (chain, "audit-op", (char *) audit_op, NULL);
nm_auth_chain_add_call (chain, permission, TRUE);
out:

View file

@ -27,6 +27,7 @@
/* core */
typedef struct _NMActiveConnection NMActiveConnection;
typedef struct _NMAuditManager NMAuditManager;
typedef struct _NMVpnConnection NMVpnConnection;
typedef struct _NMActRequest NMActRequest;
typedef struct _NMAuthSubject NMAuthSubject;

View file

@ -36,6 +36,7 @@
#include "nm-agent-manager.h"
#include "NetworkManagerUtils.h"
#include "nm-core-internal.h"
#include "nm-audit-manager.h"
#include "gsystem-local-alloc.h"
#define SETTINGS_TIMESTAMPS_FILE NMSTATEDIR "/timestamps"
@ -1320,6 +1321,11 @@ typedef struct {
gboolean save_to_disk;
} UpdateInfo;
typedef struct {
DBusGMethodInvocation *context;
NMAuthSubject *subject;
} CallbackInfo;
static void
has_some_secrets_cb (NMSetting *setting,
const char *key,
@ -1384,6 +1390,9 @@ update_complete (NMSettingsConnection *self,
else
dbus_g_method_return (info->context);
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_UPDATE, NM_CONNECTION (self), !error,
info->subject, error ? error->message : NULL);
g_clear_object (&info->subject);
g_clear_object (&info->agent_mgr);
g_clear_object (&info->new_settings);
@ -1549,6 +1558,9 @@ impl_settings_connection_update_helper (NMSettingsConnection *self,
return;
error:
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_UPDATE, NM_CONNECTION (self), FALSE, subject,
error->message);
g_clear_object (&tmp);
g_clear_object (&subject);
@ -1590,12 +1602,16 @@ con_delete_cb (NMSettingsConnection *self,
GError *error,
gpointer user_data)
{
DBusGMethodInvocation *context = user_data;
CallbackInfo *info = user_data;
if (error)
dbus_g_method_return_error (context, error);
dbus_g_method_return_error (info->context, error);
else
dbus_g_method_return (context);
dbus_g_method_return (info->context);
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DELETE, NM_CONNECTION (self),
!error, info->subject, error ? error->message : NULL);
g_free (info);
}
static void
@ -1605,12 +1621,20 @@ delete_auth_cb (NMSettingsConnection *self,
GError *error,
gpointer data)
{
CallbackInfo *info;
if (error) {
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DELETE, NM_CONNECTION (self), FALSE, subject,
error->message);
dbus_g_method_return_error (context, error);
return;
}
nm_settings_connection_delete (self, con_delete_cb, context);
info = g_malloc0 (sizeof (*info));
info->context = context;
info->subject = subject;
nm_settings_connection_delete (self, con_delete_cb, info);
}
static const char *
@ -1634,23 +1658,24 @@ static void
impl_settings_connection_delete (NMSettingsConnection *self,
DBusGMethodInvocation *context)
{
NMAuthSubject *subject;
NMAuthSubject *subject = NULL;
GError *error = NULL;
if (!check_writable (NM_CONNECTION (self), &error)) {
dbus_g_method_return_error (context, error);
g_error_free (error);
return;
}
if (!check_writable (NM_CONNECTION (self), &error))
goto out_err;
subject = _new_auth_subject (context, &error);
if (subject) {
auth_start (self, context, subject, get_modify_permission_basic (self), delete_auth_cb, NULL);
g_object_unref (subject);
} else {
dbus_g_method_return_error (context, error);
g_error_free (error);
}
} else
goto out_err;
return;
out_err:
dbus_g_method_return_error (context, error);
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DELETE, NM_CONNECTION (self), FALSE, subject, error->message);
g_error_free (error);
}
/**************************************************************/
@ -1754,12 +1779,16 @@ clear_secrets_cb (NMSettingsConnection *self,
GError *error,
gpointer user_data)
{
DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data;
CallbackInfo *info = user_data;
if (error)
dbus_g_method_return_error (context, error);
dbus_g_method_return_error (info->context, error);
else
dbus_g_method_return (context);
dbus_g_method_return (info->context);
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_CLEAR_SECRETS, NM_CONNECTION (self),
!error, info->subject, error ? error->message : NULL);
g_free (info);
}
static void
@ -1770,10 +1799,13 @@ dbus_clear_secrets_auth_cb (NMSettingsConnection *self,
gpointer user_data)
{
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
CallbackInfo *info;
if (error)
if (error) {
dbus_g_method_return_error (context, error);
else {
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_CLEAR_SECRETS, NM_CONNECTION (self),
FALSE, subject, error->message);
} else {
/* Clear secrets in connection and caches */
nm_connection_clear_secrets (NM_CONNECTION (self));
if (priv->system_secrets)
@ -1784,7 +1816,11 @@ dbus_clear_secrets_auth_cb (NMSettingsConnection *self,
/* Tell agents to remove secrets for this connection */
nm_agent_manager_delete_secrets (priv->agent_mgr, NM_CONNECTION (self));
nm_settings_connection_commit_changes (self, NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, clear_secrets_cb, context);
info = g_malloc0 (sizeof (*info));
info->context = context;
info->subject = subject;
nm_settings_connection_commit_changes (self, NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, clear_secrets_cb, info);
}
}
@ -1806,6 +1842,8 @@ impl_settings_connection_clear_secrets (NMSettingsConnection *self,
g_object_unref (subject);
} else {
dbus_g_method_return_error (context, error);
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_CLEAR_SECRETS, NM_CONNECTION (self),
FALSE, NULL, error->message);
g_error_free (error);
}
}

View file

@ -75,6 +75,7 @@
#include "nm-agent-manager.h"
#include "nm-connection-provider.h"
#include "nm-config.h"
#include "nm-audit-manager.h"
#include "NetworkManagerUtils.h"
#include "nm-dispatcher.h"
@ -1229,7 +1230,7 @@ pk_add_cb (NMAuthChain *chain,
callback_data = nm_auth_chain_get_data (chain, "callback-data");
subject = nm_auth_chain_get_data (chain, "subject");
callback (self, added, error, context, callback_data);
callback (self, added, error, context, subject, callback_data);
/* Send agent-owned secrets to the agents */
if (!error && added && nm_settings_has_connection (self, (NMConnection *) added))
@ -1371,7 +1372,7 @@ nm_settings_add_connection_dbus (NMSettings *self,
done:
if (error)
callback (self, NULL, error, context, user_data);
callback (self, NULL, error, context, subject, user_data);
g_clear_error (&error);
g_clear_object (&subject);
@ -1382,12 +1383,17 @@ impl_settings_add_connection_add_cb (NMSettings *self,
NMSettingsConnection *connection,
GError *error,
DBusGMethodInvocation *context,
NMAuthSubject *subject,
gpointer user_data)
{
if (error)
if (error) {
dbus_g_method_return_error (context, error);
else
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD, NULL, FALSE, subject, error->message);
} else {
dbus_g_method_return (context, nm_connection_get_path (NM_CONNECTION (connection)));
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD, NM_CONNECTION (connection), TRUE,
subject, NULL);
}
}
static void

View file

@ -87,6 +87,7 @@ typedef void (*NMSettingsAddCallback) (NMSettings *settings,
NMSettingsConnection *connection,
GError *error,
DBusGMethodInvocation *context,
NMAuthSubject *subject,
gpointer user_data);
void nm_settings_add_connection_dbus (NMSettings *self,