Support new PolicyKit 1.0 API

* configure.in: Check for pkcheck which indicates new policykit
* qemud/Makefile.am: Install different versions of policy
* qemud/libvirtd.policy: Rename to libvirtd.policy-0
* qemud/libvirtd.policy-1: new style policy
* qemud/qemud.c, qemud/qemud.h, qemud/remote.c: Support new
  policykit API via external pkcheck helper
* src/remote_internal.c: Don't prompt for polkit auth with new
  policykit API
* libvirt.spec.in: deal with new policy install locations & deps
This commit is contained in:
Daniel P. Berrange 2009-08-06 13:54:08 +01:00
parent 777fc2e9d6
commit 8e06c8b3da
9 changed files with 199 additions and 32 deletions

View File

@ -641,12 +641,27 @@ AC_SUBST([SASL_LIBS])
dnl PolicyKit library dnl PolicyKit library
POLKIT_CFLAGS= POLKIT_CFLAGS=
POLKIT_LIBS= POLKIT_LIBS=
PKCHECK_PATH=
AC_ARG_WITH([polkit], AC_ARG_WITH([polkit],
[ --with-polkit use PolicyKit for UNIX socket access checks], [ --with-polkit use PolicyKit for UNIX socket access checks],
[], [],
[with_polkit=check]) [with_polkit=check])
with_polkit0=no
with_polkit1=no
if test "x$with_polkit" = "xyes" -o "x$with_polkit" = "xcheck"; then if test "x$with_polkit" = "xyes" -o "x$with_polkit" = "xcheck"; then
dnl Check for new polkit first - just a binary
AC_PATH_PROG([PKCHECK_PATH],[pkcheck], [], [/usr/sbin:$PATH])
if test "x$PKCHECK_PATH" != "x" ; then
AC_DEFINE_UNQUOTED([PKCHECK_PATH],["$PKCHECK_PATH"],[Location of pkcheck program])
AC_DEFINE_UNQUOTED([HAVE_POLKIT], 1,
[use PolicyKit for UNIX socket access checks])
AC_DEFINE_UNQUOTED([HAVE_POLKIT1], 1,
[use PolicyKit for UNIX socket access checks])
with_polkit="yes"
with_polkit1="yes"
else
dnl Check for old polkit second - library + binary
PKG_CHECK_MODULES(POLKIT, polkit-dbus >= $POLKIT_REQUIRED, PKG_CHECK_MODULES(POLKIT, polkit-dbus >= $POLKIT_REQUIRED,
[with_polkit=yes], [ [with_polkit=yes], [
if test "x$with_polkit" = "xcheck" ; then if test "x$with_polkit" = "xcheck" ; then
@ -659,6 +674,8 @@ if test "x$with_polkit" = "xyes" -o "x$with_polkit" = "xcheck"; then
if test "x$with_polkit" = "xyes" ; then if test "x$with_polkit" = "xyes" ; then
AC_DEFINE_UNQUOTED([HAVE_POLKIT], 1, AC_DEFINE_UNQUOTED([HAVE_POLKIT], 1,
[use PolicyKit for UNIX socket access checks]) [use PolicyKit for UNIX socket access checks])
AC_DEFINE_UNQUOTED([HAVE_POLKIT0], 1,
[use PolicyKit for UNIX socket access checks])
old_CFLAGS=$CFLAGS old_CFLAGS=$CFLAGS
old_LDFLAGS=$LDFLAGS old_LDFLAGS=$LDFLAGS
@ -672,9 +689,13 @@ if test "x$with_polkit" = "xyes" -o "x$with_polkit" = "xcheck"; then
if test "x$POLKIT_AUTH" != "x"; then if test "x$POLKIT_AUTH" != "x"; then
AC_DEFINE_UNQUOTED([POLKIT_AUTH],["$POLKIT_AUTH"],[Location of polkit-auth program]) AC_DEFINE_UNQUOTED([POLKIT_AUTH],["$POLKIT_AUTH"],[Location of polkit-auth program])
fi fi
with_polkit0="yes"
fi
fi fi
fi fi
AM_CONDITIONAL([HAVE_POLKIT], [test "x$with_polkit" = "xyes"]) AM_CONDITIONAL([HAVE_POLKIT], [test "x$with_polkit" = "xyes"])
AM_CONDITIONAL([HAVE_POLKIT0], [test "x$with_polkit0" = "xyes"])
AM_CONDITIONAL([HAVE_POLKIT1], [test "x$with_polkit1" = "xyes"])
AC_SUBST([POLKIT_CFLAGS]) AC_SUBST([POLKIT_CFLAGS])
AC_SUBST([POLKIT_LIBS]) AC_SUBST([POLKIT_LIBS])
@ -1695,7 +1716,11 @@ else
AC_MSG_NOTICE([ avahi: no]) AC_MSG_NOTICE([ avahi: no])
fi fi
if test "$with_polkit" = "yes" ; then if test "$with_polkit" = "yes" ; then
AC_MSG_NOTICE([ polkit: $POLKIT_CFLAGS $POLKIT_LIBS]) if test "$with_polkit0" = "yes" ; then
AC_MSG_NOTICE([ polkit: $POLKIT_CFLAGS $POLKIT_LIBS (version 0)])
else
AC_MSG_NOTICE([ polkit: $PKCHECK_PATH (version 1)])
fi
else else
AC_MSG_NOTICE([ polkit: no]) AC_MSG_NOTICE([ polkit: no])
fi fi

View File

@ -95,8 +95,12 @@ Requires: iptables
# needed for device enumeration # needed for device enumeration
Requires: hal Requires: hal
%if %{with_polkit} %if %{with_polkit}
%if 0%{?fedora} >= 12
Requires: polkit >= 0.93
%else
Requires: PolicyKit >= 0.6 Requires: PolicyKit >= 0.6
%endif %endif
%endif
%if %{with_storage_fs} %if %{with_storage_fs}
# For mount/umount in FS driver # For mount/umount in FS driver
BuildRequires: util-linux BuildRequires: util-linux
@ -150,8 +154,13 @@ BuildRequires: bridge-utils
BuildRequires: cyrus-sasl-devel BuildRequires: cyrus-sasl-devel
%endif %endif
%if %{with_polkit} %if %{with_polkit}
%if 0%{?fedora} >= 12
# Only need the binary, not -devel
BuildRequires: polkit >= 0.93
%else
BuildRequires: PolicyKit-devel >= 0.6 BuildRequires: PolicyKit-devel >= 0.6
%endif %endif
%endif
%if %{with_storage_fs} %if %{with_storage_fs}
# For mount/umount in FS driver # For mount/umount in FS driver
BuildRequires: util-linux BuildRequires: util-linux
@ -525,8 +534,12 @@ fi
%endif %endif
%if %{with_polkit} %if %{with_polkit}
%if 0%{?fedora} >= 12
%{_datadir}/polkit-1/actions/org.libvirt.unix.policy
%else
%{_datadir}/PolicyKit/policy/org.libvirt.unix.policy %{_datadir}/PolicyKit/policy/org.libvirt.unix.policy
%endif %endif
%endif
%dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/ %dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/
%if %{with_qemu} %if %{with_qemu}

View File

@ -21,7 +21,8 @@ EXTRA_DIST = \
remote_protocol.x \ remote_protocol.x \
libvirtd.conf \ libvirtd.conf \
libvirtd.init.in \ libvirtd.init.in \
libvirtd.policy \ libvirtd.policy-0 \
libvirtd.policy-1 \
libvirtd.sasl \ libvirtd.sasl \
libvirtd.sysconf \ libvirtd.sysconf \
libvirtd.aug \ libvirtd.aug \
@ -147,7 +148,13 @@ endif
libvirtd_LDADD += ../src/libvirt.la libvirtd_LDADD += ../src/libvirt.la
if HAVE_POLKIT if HAVE_POLKIT
if HAVE_POLKIT0
policydir = $(datadir)/PolicyKit/policy policydir = $(datadir)/PolicyKit/policy
policyfile = libvirtd.policy-0
else
policydir = $(datadir)/polkit-1/actions
policyfile = libvirtd.policy-1
endif
endif endif
if HAVE_AVAHI if HAVE_AVAHI
@ -197,7 +204,7 @@ endif
if HAVE_POLKIT if HAVE_POLKIT
install-data-polkit:: install-init install-data-polkit:: install-init
mkdir -p $(DESTDIR)$(policydir) mkdir -p $(DESTDIR)$(policydir)
$(INSTALL_DATA) $(srcdir)/libvirtd.policy $(DESTDIR)$(policydir)/org.libvirt.unix.policy $(INSTALL_DATA) $(srcdir)/$(policyfile) $(DESTDIR)$(policydir)/org.libvirt.unix.policy
uninstall-data-polkit:: install-init uninstall-data-polkit:: install-init
rm -f $(DESTDIR)$(policydir)/org.libvirt.unix.policy rm -f $(DESTDIR)$(policydir)/org.libvirt.unix.policy
else else

42
qemud/libvirtd.policy-1 Normal file
View File

@ -0,0 +1,42 @@
<!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.unix.monitor">
<description>Monitor local virtualized systems</description>
<message>System policy prevents monitoring of local virtualized systems</message>
<defaults>
<!-- Any program can use libvirt in read-only mode for monitoring,
even if not part of a session -->
<allow_any>yes</allow_any>
<allow_inactive>yes</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="org.libvirt.unix.manage">
<description>Manage local virtualized systems</description>
<message>System policy prevents management of local virtualized systems</message>
<defaults>
<!-- Only a program in the active host session can use libvirt in
read-write mode for management, and we require user password -->
<allow_any>no</allow_any>
<allow_inactive>no</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
</policyconfig>

View File

@ -890,7 +890,7 @@ static struct qemud_server *qemudNetworkInit(struct qemud_server *server) {
} }
#endif #endif
#ifdef HAVE_POLKIT #if HAVE_POLKIT0
if (auth_unix_rw == REMOTE_AUTH_POLKIT || if (auth_unix_rw == REMOTE_AUTH_POLKIT ||
auth_unix_ro == REMOTE_AUTH_POLKIT) { auth_unix_ro == REMOTE_AUTH_POLKIT) {
DBusError derr; DBusError derr;
@ -977,7 +977,7 @@ static struct qemud_server *qemudNetworkInit(struct qemud_server *server) {
sock = sock->next; sock = sock->next;
} }
#ifdef HAVE_POLKIT #if HAVE_POLKIT0
if (server->sysbus) if (server->sysbus)
dbus_connection_unref(server->sysbus); dbus_connection_unref(server->sysbus);
#endif #endif

View File

@ -34,7 +34,7 @@
#include <sasl/sasl.h> #include <sasl/sasl.h>
#endif #endif
#ifdef HAVE_POLKIT #if HAVE_POLKIT0
#include <dbus/dbus.h> #include <dbus/dbus.h>
#endif #endif
@ -253,7 +253,7 @@ struct qemud_server {
#if HAVE_SASL #if HAVE_SASL
char **saslUsernameWhitelist; char **saslUsernameWhitelist;
#endif #endif
#if HAVE_POLKIT #if HAVE_POLKIT0
DBusConnection *sysbus; DBusConnection *sysbus;
#endif #endif
}; };

View File

@ -43,7 +43,7 @@
#include <fnmatch.h> #include <fnmatch.h>
#include "virterror_internal.h" #include "virterror_internal.h"
#ifdef HAVE_POLKIT #if HAVE_POLKIT0
#include <polkit/polkit.h> #include <polkit/polkit.h>
#include <polkit-dbus/polkit-dbus.h> #include <polkit-dbus/polkit-dbus.h>
#endif #endif
@ -3106,7 +3106,80 @@ remoteDispatchAuthSaslStep (struct qemud_server *server ATTRIBUTE_UNUSED,
#endif /* HAVE_SASL */ #endif /* HAVE_SASL */
#if HAVE_POLKIT #if HAVE_POLKIT1
static int
remoteDispatchAuthPolkit (struct qemud_server *server,
struct qemud_client *client,
virConnectPtr conn ATTRIBUTE_UNUSED,
remote_error *rerr,
void *args ATTRIBUTE_UNUSED,
remote_auth_polkit_ret *ret)
{
pid_t callerPid;
uid_t callerUid;
const char *action;
int status = -1;
char pidbuf[50];
int rv;
virMutexLock(&server->lock);
virMutexLock(&client->lock);
virMutexUnlock(&server->lock);
action = client->readonly ?
"org.libvirt.unix.monitor" :
"org.libvirt.unix.manage";
const char * const pkcheck [] = {
PKCHECK_PATH,
"--action-id", action,
"--process", pidbuf,
"--allow-user-interaction",
NULL
};
REMOTE_DEBUG("Start PolicyKit auth %d", client->fd);
if (client->auth != REMOTE_AUTH_POLKIT) {
VIR_ERROR0(_("client tried invalid PolicyKit init request"));
goto authfail;
}
if (qemudGetSocketIdentity(client->fd, &callerUid, &callerPid) < 0) {
VIR_ERROR0(_("cannot get peer socket identity"));
goto authfail;
}
VIR_INFO(_("Checking PID %d running as %d"), callerPid, callerUid);
rv = snprintf(pidbuf, sizeof pidbuf, "%d", callerPid);
if (rv < 0 || rv >= sizeof pidbuf) {
VIR_ERROR(_("Caller PID was too large %d"), callerPid);
goto authfail;
}
if (virRun(NULL, pkcheck, &status) < 0) {
VIR_ERROR(_("Cannot invoke %s"), PKCHECK_PATH);
goto authfail;
}
if (status != 0) {
VIR_ERROR(_("Policy kit denied action %s from pid %d, uid %d, result: %d\n"),
action, callerPid, callerUid, status);
goto authfail;
}
VIR_INFO(_("Policy allowed action %s from pid %d, uid %d"),
action, callerPid, callerUid);
ret->complete = 1;
client->auth = REMOTE_AUTH_NONE;
virMutexUnlock(&client->lock);
return 0;
authfail:
remoteDispatchAuthError(rerr);
virMutexUnlock(&client->lock);
return -1;
}
#elif HAVE_POLKIT0
static int static int
remoteDispatchAuthPolkit (struct qemud_server *server, remoteDispatchAuthPolkit (struct qemud_server *server,
struct qemud_client *client, struct qemud_client *client,
@ -3217,7 +3290,7 @@ authfail:
return -1; return -1;
} }
#else /* HAVE_POLKIT */ #else /* !HAVE_POLKIT0 & !HAVE_POLKIT1*/
static int static int
remoteDispatchAuthPolkit (struct qemud_server *server ATTRIBUTE_UNUSED, remoteDispatchAuthPolkit (struct qemud_server *server ATTRIBUTE_UNUSED,
@ -3231,7 +3304,7 @@ remoteDispatchAuthPolkit (struct qemud_server *server ATTRIBUTE_UNUSED,
remoteDispatchAuthError(rerr); remoteDispatchAuthError(rerr);
return -1; return -1;
} }
#endif /* HAVE_POLKIT */ #endif /* HAVE_POLKIT1 */
/*************************************************************** /***************************************************************

View File

@ -6201,6 +6201,7 @@ remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int in_open,
virConnectAuthPtr auth) virConnectAuthPtr auth)
{ {
remote_auth_polkit_ret ret; remote_auth_polkit_ret ret;
#if HAVE_POLKIT0
int i, allowcb = 0; int i, allowcb = 0;
virConnectCredential cred = { virConnectCredential cred = {
VIR_CRED_EXTERNAL, VIR_CRED_EXTERNAL,
@ -6210,8 +6211,10 @@ remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int in_open,
NULL, NULL,
0, 0,
}; };
#endif
DEBUG0("Client initialize PolicyKit authentication"); DEBUG0("Client initialize PolicyKit authentication");
#if HAVE_POLKIT0
if (auth && auth->cb) { if (auth && auth->cb) {
/* Check if the necessary credential type for PolicyKit is supported */ /* Check if the necessary credential type for PolicyKit is supported */
for (i = 0 ; i < auth->ncredtype ; i++) { for (i = 0 ; i < auth->ncredtype ; i++) {
@ -6220,6 +6223,7 @@ remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int in_open,
} }
if (allowcb) { if (allowcb) {
DEBUG0("Client run callback for PolicyKit authentication");
/* Run the authentication callback */ /* Run the authentication callback */
if ((*(auth->cb))(&cred, 1, auth->cbdata) < 0) { if ((*(auth->cb))(&cred, 1, auth->cbdata) < 0) {
virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE,
@ -6233,6 +6237,9 @@ remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int in_open,
} else { } else {
DEBUG0("No auth callback provided"); DEBUG0("No auth callback provided");
} }
#else
DEBUG0("No auth callback required for PolicyKit-1");
#endif
memset (&ret, 0, sizeof ret); memset (&ret, 0, sizeof ret);
if (call (conn, priv, in_open, REMOTE_PROC_AUTH_POLKIT, if (call (conn, priv, in_open, REMOTE_PROC_AUTH_POLKIT,