summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2015-07-20 18:33:35 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2015-08-04 09:32:12 +0200
commitbe49a59fb649d7383b456403deb323a2eb9dab4b (patch)
treebc4b02c290061acc03d93ef8fb4f092431322f9d
parent41e7051165166839c7e44f644dc750169d233e96 (diff)
downloadNetworkManager-be49a59fb649d7383b456403deb323a2eb9dab4b.tar.gz
core: add audit support
Introduce some primitives to deliver messages about relevant configuration changes to the Linux audit subsystem through libaudit (if enabled at build time) and to the logging system.
-rw-r--r--configure.ac17
-rw-r--r--contrib/fedora/rpm/NetworkManager.conf1
-rw-r--r--contrib/fedora/rpm/NetworkManager.spec2
-rw-r--r--man/NetworkManager.conf.xml.in9
-rw-r--r--src/Makefile.am6
-rw-r--r--src/nm-audit-manager.c371
-rw-r--r--src/nm-audit-manager.h112
-rw-r--r--src/nm-config.h1
-rw-r--r--src/nm-types.h1
9 files changed, 519 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index a6cf8d8156..ed973998e6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -494,6 +494,22 @@ else
AC_DEFINE(HAVE_SELINUX, 0, [Define if you have SELinux support])
fi
+# 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)
@@ -1108,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:"
diff --git a/contrib/fedora/rpm/NetworkManager.conf b/contrib/fedora/rpm/NetworkManager.conf
index 0352aa1087..6efa736d92 100644
--- a/contrib/fedora/rpm/NetworkManager.conf
+++ b/contrib/fedora/rpm/NetworkManager.conf
@@ -23,3 +23,4 @@
[logging]
#level=DEBUG
+#audit=yes
diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec
index 048cedae1f..2d9618dfdb 100644
--- a/contrib/fedora/rpm/NetworkManager.spec
+++ b/contrib/fedora/rpm/NetworkManager.spec
@@ -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
diff --git a/man/NetworkManager.conf.xml.in b/man/NetworkManager.conf.xml.in
index 38c3b310d1..850e772fc1 100644
--- a/man/NetworkManager.conf.xml.in
+++ b/man/NetworkManager.conf.xml.in
@@ -485,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>
diff --git a/src/Makefile.am b/src/Makefile.am
index 46f02aec19..a5d7973a77 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -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) \
@@ -460,7 +463,8 @@ libNetworkManager_la_LIBADD = \
$(LIBNDP_LIBS) \
$(LIBDL) \
$(LIBM) \
- $(SELINUX_LIBS)
+ $(SELINUX_LIBS) \
+ $(LIBAUDIT_LIBS)
if WITH_LIBSOUP
libNetworkManager_la_LIBADD += $(LIBSOUP_LIBS)
diff --git a/src/nm-audit-manager.c b/src/nm-audit-manager.c
new file mode 100644
index 0000000000..22ebf3b054
--- /dev/null
+++ b/src/nm-audit-manager.c
@@ -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;
+}
+
diff --git a/src/nm-audit-manager.h b/src/nm-audit-manager.h
new file mode 100644
index 0000000000..83d969c864
--- /dev/null
+++ b/src/nm-audit-manager.h
@@ -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__ */
diff --git a/src/nm-config.h b/src/nm-config.h
index 2eece45a15..e492999f99 100644
--- a/src/nm-config.h
+++ b/src/nm-config.h
@@ -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."
diff --git a/src/nm-types.h b/src/nm-types.h
index 7d3cf48129..7e9d488a18 100644
--- a/src/nm-types.h
+++ b/src/nm-types.h
@@ -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;