From: "Daniel P. Berrange" <berrange(a)redhat.com>
---
po/POTFILES.in | 1 +
src/Makefile.am | 12 ++-
src/access/org.libvirt.domain.policy | 37 ++++++++
src/access/viraccessdriverpolkit.c | 163 ++++++++++++++++++++++++++++++++++
src/access/viraccessdriverpolkit.h | 28 ++++++
src/access/viraccessmanager.c | 2 +
6 files changed, 241 insertions(+), 2 deletions(-)
create mode 100644 src/access/org.libvirt.domain.policy
create mode 100644 src/access/viraccessdriverpolkit.c
create mode 100644 src/access/viraccessdriverpolkit.h
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f898887..0c18fa0 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -6,6 +6,7 @@ daemon/remote_dispatch.h
daemon/stream.c
gnulib/lib/gai_strerror.c
gnulib/lib/regcomp.c
+src/access/viraccessdriverpolkit.c
src/access/viraccessmanager.c
src/conf/cpu_conf.c
src/conf/domain_conf.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 0293562..f9972ac 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -536,7 +536,12 @@ ACCESS_DRIVER_SOURCES = \
access/viraccessmanager.h access/viraccessmanager.c \
access/viraccessdriver.h \
access/viraccessdrivernop.h access/viraccessdrivernop.c \
- access/viraccessdriverstack.h access/viraccessdriverstack.c
+ access/viraccessdriverstack.h access/viraccessdriverstack.c \
+ access/viraccessdriverpolkit.h access/viraccessdriverpolkit.c
+
+ACCESS_DRIVER_POLKIT_POLICY = \
+ access/org.libvirt.domain.policy
+
NODE_DEVICE_DRIVER_SOURCES = \
node_device/node_device_driver.c \
@@ -1130,6 +1135,8 @@ libvirt_driver_access_la_CFLAGS = \
libvirt_driver_access_la_LDFLAGS = $(AM_LDFLAGS)
libvirt_driver_access_la_LIBADD =
+polkitactiondir = $(datadir)/polkit-1/actions
+polkitaction_DATA = $(ACCESS_DRIVER_POLKIT_POLICY)
# Add all conditional sources just in case...
EXTRA_DIST += \
@@ -1166,7 +1173,8 @@ EXTRA_DIST += \
$(SECRET_DRIVER_SOURCES) \
$(VBOX_DRIVER_EXTRA_DIST) \
$(VMWARE_DRIVER_SOURCES) \
- $(XENXS_SOURCES)
+ $(XENXS_SOURCES) \
+ $(ACCESS_DRIVER_POLKIT_POLICY)
check-local: augeas-check
diff --git a/src/access/org.libvirt.domain.policy b/src/access/org.libvirt.domain.policy
new file mode 100644
index 0000000..a8ebd84
--- /dev/null
+++ b/src/access/org.libvirt.domain.policy
@@ -0,0 +1,37 @@
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+
+<!--
+Policy definitions for libvirt daemon
+
+Copyright (c) 2007 Daniel P. Berrange <berrange redhat com>
+
+libvirt is licensed to you under the GNU Lesser General Public License
+version 2. See COPYING for details.
+
+NOTE: If you make changes to this file, make sure to validate the file
+using the polkit-policy-file-validate(1) tool. Changes made to this
+file are instantly applied.
+-->
+
+<policyconfig>
+ <action id="org.libvirt.domain.getattr">
+ <description>Get virtual domain attributes</description>
+ <message>System policy prevents getattr on guest domains</message>
+ <defaults>
+ <allow_any>yes</allow_any>
+ <allow_inactive>yes</allow_inactive>
+ <allow_active>yes</allow_active>
+ </defaults>
+ </action>
+ <action id="org.libvirt.domain.read">
+ <description>Get virtual domain attributes</description>
+ <message>System policy prevents getattr on guest domains</message>
+ <defaults>
+ <allow_any>yes</allow_any>
+ <allow_inactive>yes</allow_inactive>
+ <allow_active>yes</allow_active>
+ </defaults>
+ </action>
+</policyconfig>
diff --git a/src/access/viraccessdriverpolkit.c b/src/access/viraccessdriverpolkit.c
new file mode 100644
index 0000000..8364986
--- /dev/null
+++ b/src/access/viraccessdriverpolkit.c
@@ -0,0 +1,163 @@
+/*
+ * viraccessdriverpolkit.c: polkited access control driver
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <config.h>
+
+#include "access/viraccessdriverpolkit.h"
+#include "memory.h"
+#include "command.h"
+#include "logging.h"
+#include "virterror_internal.h"
+
+#define VIR_FROM_THIS VIR_FROM_ACCESS
+#define virAccessError(code, ...) \
+ virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \
+ __FUNCTION__, __LINE__, __VA_ARGS__)
+
+#define VIR_ACCESS_DRIVER_POLKIT_ACTION_PREFIX "org.libvirt"
+
+typedef struct _virAccessDriverPolkitPrivate virAccessDriverPolkitPrivate;
+typedef virAccessDriverPolkitPrivate *virAccessDriverPolkitPrivatePtr;
+
+struct _virAccessDriverPolkitPrivate {
+ bool ignore;
+};
+
+
+static void virAccessDriverPolkitCleanup(virAccessManagerPtr manager ATTRIBUTE_UNUSED)
+{
+}
+
+
+static char *
+virAccessDriverPolkitFormatAction(const char *typename,
+ const char *avname)
+{
+ char *actionid = NULL;
+
+ if (virAsprintf(&actionid, "%s.%s.%s",
+ VIR_ACCESS_DRIVER_POLKIT_ACTION_PREFIX,
+ typename, avname) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ return actionid;
+}
+
+
+static char *
+virAccessDriverPolkitFormatProcess(void)
+{
+ virIdentityPtr identity = virAccessManagerGetEffectiveIdentity();
+ const char *process = NULL;
+ char *ret = NULL;
+
+ if (!identity) {
+ virAccessError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("No identity available"));
+ return NULL;
+ }
+ if (virIdentityGetAttr(identity, VIR_IDENTITY_ATTR_UNIX_PROCESS_ID, &process)
< 0)
+ goto cleanup;
+
+ if (!process) {
+ virAccessError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("No UNIX process ID available"));
+ goto cleanup;
+ }
+
+ if (!(ret = strdup(process))) {
+ virReportOOMError();
+ goto cleanup;
+ }
+cleanup:
+ virIdentityFree(identity);
+ return ret;
+}
+
+
+static bool
+virAccessDriverPolkitCheck(virAccessManagerPtr manager ATTRIBUTE_UNUSED,
+ const char *typename,
+ const char *avname)
+{
+ char *actionid = virAccessDriverPolkitFormatAction(typename, avname);
+ char *process = virAccessDriverPolkitFormatProcess();
+ virCommandPtr cmd;
+ int status;
+ int ret = false;
+
+ if (!actionid || !process)
+ goto cleanup;
+
+ cmd = virCommandNewArgList(PKCHECK_PATH,
+ "--action-id", actionid,
+ "--process", process,
+ NULL);
+
+ if (virCommandRun(cmd, &status) < 0)
+ goto cleanup;
+
+ if (status != 0) {
+ char *tmp = virCommandTranslateStatus(status);
+ virAccessError(VIR_ERR_ACCESS_DENIED,
+ _("Policy kit denied action %s from %s: %s"),
+ actionid, process, NULLSTR(tmp));
+ VIR_FREE(tmp);
+ goto cleanup;
+ }
+
+ ret = true;
+
+cleanup:
+ VIR_FREE(actionid);
+ VIR_FREE(process);
+ return ret;
+}
+
+
+static bool
+virAccessDriverPolkitCheckConnect(virAccessManagerPtr manager,
+ virAccessPermConnect av)
+{
+ return virAccessDriverPolkitCheck(manager,
+ "connect",
+ virAccessPermConnectTypeToString(av));
+}
+
+
+static bool
+virAccessDriverPolkitCheckDomain(virAccessManagerPtr manager,
+ virDomainDefPtr def ATTRIBUTE_UNUSED,
+ virAccessPermDomain av)
+{
+ return virAccessDriverPolkitCheck(manager,
+ "domain",
+ virAccessPermDomainTypeToString(av));
+}
+
+
+virAccessDriver accessDriverPolkit = {
+ .name = "polkit",
+ .cleanup = virAccessDriverPolkitCleanup,
+ .checkConnect = virAccessDriverPolkitCheckConnect,
+ .checkDomain = virAccessDriverPolkitCheckDomain,
+};
diff --git a/src/access/viraccessdriverpolkit.h b/src/access/viraccessdriverpolkit.h
new file mode 100644
index 0000000..ac71fa5
--- /dev/null
+++ b/src/access/viraccessdriverpolkit.h
@@ -0,0 +1,28 @@
+/*
+ * viraccessdriverpolkit.h: polkited access control driver
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __VIR_ACCESS_DRIVER_POLKIT_H__
+# define __VIR_ACCESS_DRIVER_POLKIT_H__
+
+# include "access/viraccessdriver.h"
+
+extern virAccessDriver accessDriverPolkit;
+
+#endif /* __VIR_ACCESS_DRIVER_POLKIT_H__ */
diff --git a/src/access/viraccessmanager.c b/src/access/viraccessmanager.c
index 4e77bd6..e7444d5 100644
--- a/src/access/viraccessmanager.c
+++ b/src/access/viraccessmanager.c
@@ -29,6 +29,7 @@
#endif
#include "access/viraccessdrivernop.h"
#include "access/viraccessdriverstack.h"
+#include "access/viraccessdriverpolkit.h"
#include "logging.h"
#define VIR_FROM_THIS VIR_FROM_ACCESS
@@ -216,6 +217,7 @@ static virAccessManagerPtr
virAccessManagerNewDriver(virAccessDriverPtr drv)
static virAccessDriverPtr accessDrivers[] = {
&accessDriverNop,
+ &accessDriverPolkit,
};
--
1.7.10