mirror of https://gitee.com/openkylin/libvirt.git
Added PolicyKit authentication support
This commit is contained in:
parent
f8f1977826
commit
282342c1c5
16
ChangeLog
16
ChangeLog
|
@ -1,3 +1,19 @@
|
||||||
|
Wed Dec 5 13:20:00 EST 2007 Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
|
||||||
|
* configure.in: do PolicyKit checks via pkg-config
|
||||||
|
* libvirt.spec.in: Add dep on PolicyKit if Fedora 8 or later
|
||||||
|
* qemud/Makefile.am: Add PolicyKit build flags and default
|
||||||
|
policy file
|
||||||
|
* qemud/libvirtd.conf: Add comment about polkit auth option
|
||||||
|
* qemud/libvirtd.policy: Default policy file
|
||||||
|
* qemud/qemud.c, qemud/remote.c: Implementation of PolicyKit
|
||||||
|
authentication
|
||||||
|
* qemud/remote_protocol.x: Add RPC calls for PolicyKit auth
|
||||||
|
* qemud/remote_dispatch*, qemud/remote_protocol.{c.h}: update
|
||||||
|
for new RPC calls.
|
||||||
|
* src/remote_internal.c: Fetch credentials for PolicyKit and
|
||||||
|
perform client part of auth process
|
||||||
|
|
||||||
Wed Dec 5 18:00:00 UTC 2007 Richard W.M. Jones <rjones@redhat.com>
|
Wed Dec 5 18:00:00 UTC 2007 Richard W.M. Jones <rjones@redhat.com>
|
||||||
|
|
||||||
* src/Makefile.am, tests/Makefile.am: Remove LIBOBJS/LTLIBOBJS
|
* src/Makefile.am, tests/Makefile.am: Remove LIBOBJS/LTLIBOBJS
|
||||||
|
|
25
configure.in
25
configure.in
|
@ -25,6 +25,7 @@ dnl Required minimum versions of all libs we depend on
|
||||||
LIBXML_REQUIRED="2.5.0"
|
LIBXML_REQUIRED="2.5.0"
|
||||||
GNUTLS_REQUIRED="1.0.25"
|
GNUTLS_REQUIRED="1.0.25"
|
||||||
AVAHI_REQUIRED="0.6.0"
|
AVAHI_REQUIRED="0.6.0"
|
||||||
|
POLKIT_REQUIRED="0.6"
|
||||||
|
|
||||||
dnl Checks for C compiler.
|
dnl Checks for C compiler.
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
@ -394,6 +395,25 @@ AC_SUBST(SASL_CFLAGS)
|
||||||
AC_SUBST(SASL_LIBS)
|
AC_SUBST(SASL_LIBS)
|
||||||
|
|
||||||
|
|
||||||
|
dnl PolicyKit library
|
||||||
|
POLKIT_CFLAGS=
|
||||||
|
POLKIT_LIBS=
|
||||||
|
AC_ARG_WITH(polkit,
|
||||||
|
[ --with-polkit use PolicyKit for UNIX socket access checks],
|
||||||
|
[],
|
||||||
|
[with_polkit=check])
|
||||||
|
|
||||||
|
if test "$with_polkit" = "check"; then
|
||||||
|
PKG_CHECK_EXISTS(polkit-dbus >= $POLKIT_REQUIRED, [with_polkit=yes], [with_polkit=no])
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$with_polkit" = "yes"; then
|
||||||
|
PKG_CHECK_MODULES(POLKIT, polkit-dbus >= $POLKIT_REQUIRED)
|
||||||
|
AC_DEFINE_UNQUOTED(HAVE_POLKIT, 1, [use PolicyKit for UNIX socket access checks])
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(HAVE_POLKIT, [test "$with_polkit" = "yes"])
|
||||||
|
AC_SUBST(POLKIT_CFLAGS)
|
||||||
|
AC_SUBST(POLKIT_LIBS)
|
||||||
|
|
||||||
dnl Avahi library
|
dnl Avahi library
|
||||||
AC_ARG_WITH(avahi,
|
AC_ARG_WITH(avahi,
|
||||||
|
@ -627,6 +647,11 @@ AC_MSG_NOTICE([ avahi: $AVAHI_CFLAGS $AVAHI_LIBS])
|
||||||
else
|
else
|
||||||
AC_MSG_NOTICE([ avahi: no])
|
AC_MSG_NOTICE([ avahi: no])
|
||||||
fi
|
fi
|
||||||
|
if test "$with_polkit" = "yes" ; then
|
||||||
|
AC_MSG_NOTICE([ polkit: $POLKIT_CFLAGS $POLKIT_LIBS])
|
||||||
|
else
|
||||||
|
AC_MSG_NOTICE([ polkit: no])
|
||||||
|
fi
|
||||||
AC_MSG_NOTICE([])
|
AC_MSG_NOTICE([])
|
||||||
AC_MSG_NOTICE([Miscellaneous])
|
AC_MSG_NOTICE([Miscellaneous])
|
||||||
AC_MSG_NOTICE([])
|
AC_MSG_NOTICE([])
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
# -*- rpm-spec -*-
|
# -*- rpm-spec -*-
|
||||||
|
|
||||||
|
%if %{fedora} >= 8
|
||||||
|
%define with_polkit 1
|
||||||
|
%else
|
||||||
|
%define with_polkit 0
|
||||||
|
%endif
|
||||||
|
|
||||||
Summary: Library providing a simple API virtualization
|
Summary: Library providing a simple API virtualization
|
||||||
Name: libvirt
|
Name: libvirt
|
||||||
Version: @VERSION@
|
Version: @VERSION@
|
||||||
|
@ -20,6 +26,9 @@ Requires: cyrus-sasl
|
||||||
# Not technically required, but makes 'out-of-box' config
|
# Not technically required, but makes 'out-of-box' config
|
||||||
# work correctly & doesn't have onerous dependancies
|
# work correctly & doesn't have onerous dependancies
|
||||||
Requires: cyrus-sasl-md5
|
Requires: cyrus-sasl-md5
|
||||||
|
%if %{with_polkit}
|
||||||
|
Requires: PolicyKit >= 0.6
|
||||||
|
%endif
|
||||||
BuildRequires: xen-devel
|
BuildRequires: xen-devel
|
||||||
BuildRequires: libxml2-devel
|
BuildRequires: libxml2-devel
|
||||||
BuildRequires: readline-devel
|
BuildRequires: readline-devel
|
||||||
|
@ -31,6 +40,9 @@ BuildRequires: dnsmasq
|
||||||
BuildRequires: bridge-utils
|
BuildRequires: bridge-utils
|
||||||
BuildRequires: qemu
|
BuildRequires: qemu
|
||||||
BuildRequires: cyrus-sasl-devel
|
BuildRequires: cyrus-sasl-devel
|
||||||
|
%if %{with_polkit}
|
||||||
|
BuildRequires: PolicyKit-devel >= 0.6
|
||||||
|
%endif
|
||||||
Obsoletes: libvir
|
Obsoletes: libvir
|
||||||
ExclusiveArch: i386 x86_64 ia64
|
ExclusiveArch: i386 x86_64 ia64
|
||||||
|
|
||||||
|
@ -143,6 +155,7 @@ fi
|
||||||
%{_datadir}/libvirt/networks/default.xml
|
%{_datadir}/libvirt/networks/default.xml
|
||||||
%dir %{_localstatedir}/run/libvirt/
|
%dir %{_localstatedir}/run/libvirt/
|
||||||
%dir %{_localstatedir}/lib/libvirt/
|
%dir %{_localstatedir}/lib/libvirt/
|
||||||
|
%{_datadir}/PolicyKit/policy/libvirtd.policy
|
||||||
%dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/qemu/
|
%dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/qemu/
|
||||||
%attr(4755, root, root) %{_libexecdir}/libvirt_proxy
|
%attr(4755, root, root) %{_libexecdir}/libvirt_proxy
|
||||||
%attr(0755, root, root) %{_sbindir}/libvirtd
|
%attr(0755, root, root) %{_sbindir}/libvirtd
|
||||||
|
|
|
@ -30,16 +30,25 @@ libvirtd_SOURCES = \
|
||||||
libvirtd_CFLAGS = \
|
libvirtd_CFLAGS = \
|
||||||
-I$(top_srcdir)/include -I$(top_builddir)/include \
|
-I$(top_srcdir)/include -I$(top_builddir)/include \
|
||||||
$(LIBXML_CFLAGS) $(GNUTLS_CFLAGS) $(SASL_CFLAGS) \
|
$(LIBXML_CFLAGS) $(GNUTLS_CFLAGS) $(SASL_CFLAGS) \
|
||||||
|
$(POLKIT_CFLAGS) \
|
||||||
$(WARN_CFLAGS) -DLOCAL_STATE_DIR="\"$(localstatedir)\"" \
|
$(WARN_CFLAGS) -DLOCAL_STATE_DIR="\"$(localstatedir)\"" \
|
||||||
-DSYSCONF_DIR="\"$(sysconfdir)\"" \
|
-DSYSCONF_DIR="\"$(sysconfdir)\"" \
|
||||||
-DQEMUD_PID_FILE="\"$(QEMUD_PID_FILE)\"" \
|
-DQEMUD_PID_FILE="\"$(QEMUD_PID_FILE)\"" \
|
||||||
-DREMOTE_PID_FILE="\"$(REMOTE_PID_FILE)\"" \
|
-DREMOTE_PID_FILE="\"$(REMOTE_PID_FILE)\"" \
|
||||||
-DGETTEXT_PACKAGE=\"$(PACKAGE)\"
|
-DGETTEXT_PACKAGE=\"$(PACKAGE)\"
|
||||||
|
|
||||||
libvirtd_LDFLAGS = $(WARN_CFLAGS) $(LIBXML_LIBS) $(GNUTLS_LIBS) $(SASL_LIBS)
|
libvirtd_LDFLAGS = $(WARN_CFLAGS) $(LIBXML_LIBS) $(GNUTLS_LIBS) $(SASL_LIBS) \
|
||||||
|
$(POLKIT_LIBS)
|
||||||
libvirtd_DEPENDENCIES = ../src/libvirt.la
|
libvirtd_DEPENDENCIES = ../src/libvirt.la
|
||||||
libvirtd_LDADD = ../src/libvirt.la
|
libvirtd_LDADD = ../src/libvirt.la
|
||||||
|
|
||||||
|
|
||||||
|
if HAVE_POLKIT
|
||||||
|
policydir = $(datadir)/PolicyKit/policy
|
||||||
|
policy_DATA = libvirtd.policy
|
||||||
|
endif
|
||||||
|
EXTRA_DIST += libvirtd.policy
|
||||||
|
|
||||||
if HAVE_AVAHI
|
if HAVE_AVAHI
|
||||||
libvirtd_SOURCES += mdns.c mdns.h
|
libvirtd_SOURCES += mdns.c mdns.h
|
||||||
libvirtd_CFLAGS += $(AVAHI_CFLAGS)
|
libvirtd_CFLAGS += $(AVAHI_CFLAGS)
|
||||||
|
|
|
@ -32,6 +32,10 @@
|
||||||
#include <sasl/sasl.h>
|
#include <sasl/sasl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_POLKIT
|
||||||
|
#include <dbus/dbus.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SYS_SYSLIMITS_H
|
#ifdef HAVE_SYS_SYSLIMITS_H
|
||||||
#include <sys/syslimits.h>
|
#include <sys/syslimits.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -155,6 +159,9 @@ struct qemud_server {
|
||||||
#if HAVE_SASL
|
#if HAVE_SASL
|
||||||
char **saslUsernameWhitelist;
|
char **saslUsernameWhitelist;
|
||||||
#endif
|
#endif
|
||||||
|
#if HAVE_POLKIT
|
||||||
|
DBusConnection *sysbus;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
void qemudLog(int priority, const char *fmt, ...)
|
void qemudLog(int priority, const char *fmt, ...)
|
||||||
|
|
|
@ -82,8 +82,11 @@
|
||||||
# Set the UNIX socket permissions for the R/W socket. This is used
|
# Set the UNIX socket permissions for the R/W socket. This is used
|
||||||
# for full management of VMs
|
# for full management of VMs
|
||||||
#
|
#
|
||||||
# Default allows only root. If setting group ownership may want to
|
# Default allows only root. If PolicyKit is enabled on the socket,
|
||||||
# relax this to:
|
# the default will change to allow everyone (eg, 0777)
|
||||||
|
#
|
||||||
|
# If not using PolicyKit and setting group ownership for access
|
||||||
|
# control then you may want to relax this to:
|
||||||
#unix_sock_rw_perms = "0770"
|
#unix_sock_rw_perms = "0770"
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,7 +106,12 @@
|
||||||
# socket only GSSAPI & DIGEST-MD5 mechanisms will be used.
|
# socket only GSSAPI & DIGEST-MD5 mechanisms will be used.
|
||||||
# For non-TCP or TLS sockets, any scheme is allowed.
|
# For non-TCP or TLS sockets, any scheme is allowed.
|
||||||
#
|
#
|
||||||
|
# - polkit: use PolicyKit to authenticate. This is only suitable
|
||||||
|
# for use on the UNIX sockets. The default policy will
|
||||||
|
# require a user to supply their own password to gain
|
||||||
|
# full read/write access (aka sudo like), while anyone
|
||||||
|
# is allowed read/only access.
|
||||||
|
#
|
||||||
# Set an authentication scheme for UNIX read-only sockets
|
# Set an authentication scheme for UNIX read-only sockets
|
||||||
# By default socket permissions allow anyone to connect
|
# By default socket permissions allow anyone to connect
|
||||||
#
|
#
|
||||||
|
@ -112,7 +120,9 @@
|
||||||
#auth_unix_ro = "none"
|
#auth_unix_ro = "none"
|
||||||
|
|
||||||
# Set an authentication scheme for UNIX read-write sockets
|
# Set an authentication scheme for UNIX read-write sockets
|
||||||
# By default socket permissions only allow root.
|
# By default socket permissions only allow root. If PolicyKit
|
||||||
|
# support was compiled into libvirt, the default will be to
|
||||||
|
# use 'polkit' auth.
|
||||||
#
|
#
|
||||||
# If the unix_sock_rw_perms are changed you may wish to enable
|
# If the unix_sock_rw_perms are changed you may wish to enable
|
||||||
# an authentication mechanism here
|
# an authentication mechanism here
|
||||||
|
|
|
@ -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_self_keep_session</allow_active>
|
||||||
|
</defaults>
|
||||||
|
</action>
|
||||||
|
</policyconfig>
|
|
@ -77,8 +77,13 @@ static gid_t unix_sock_gid = 0; /* Only root by default */
|
||||||
static int unix_sock_rw_mask = 0700; /* Allow user only */
|
static int unix_sock_rw_mask = 0700; /* Allow user only */
|
||||||
static int unix_sock_ro_mask = 0777; /* Allow world */
|
static int unix_sock_ro_mask = 0777; /* Allow world */
|
||||||
|
|
||||||
|
#if HAVE_POLKIT
|
||||||
|
static int auth_unix_rw = REMOTE_AUTH_POLKIT;
|
||||||
|
static int auth_unix_ro = REMOTE_AUTH_POLKIT;
|
||||||
|
#else
|
||||||
static int auth_unix_rw = REMOTE_AUTH_NONE;
|
static int auth_unix_rw = REMOTE_AUTH_NONE;
|
||||||
static int auth_unix_ro = REMOTE_AUTH_NONE;
|
static int auth_unix_ro = REMOTE_AUTH_NONE;
|
||||||
|
#endif /* HAVE_POLKIT */
|
||||||
#if HAVE_SASL
|
#if HAVE_SASL
|
||||||
static int auth_tcp = REMOTE_AUTH_SASL;
|
static int auth_tcp = REMOTE_AUTH_SASL;
|
||||||
#else
|
#else
|
||||||
|
@ -759,6 +764,21 @@ static struct qemud_server *qemudNetworkInit(struct qemud_server *server) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_POLKIT
|
||||||
|
if (auth_unix_rw == REMOTE_AUTH_POLKIT ||
|
||||||
|
auth_unix_ro == REMOTE_AUTH_POLKIT) {
|
||||||
|
DBusError derr;
|
||||||
|
dbus_error_init(&derr);
|
||||||
|
server->sysbus = dbus_bus_get(DBUS_BUS_SYSTEM, &derr);
|
||||||
|
if (!(server->sysbus)) {
|
||||||
|
qemudLog(QEMUD_ERR, "Failed to connect to system bus for PolicyKit auth: %s",
|
||||||
|
derr.message);
|
||||||
|
dbus_error_free(&derr);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ipsock) {
|
if (ipsock) {
|
||||||
if (listen_tcp && remoteListenTCP (server, tcp_port, QEMUD_SOCK_TYPE_TCP, auth_tcp) < 0)
|
if (listen_tcp && remoteListenTCP (server, tcp_port, QEMUD_SOCK_TYPE_TCP, auth_tcp) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -826,6 +846,10 @@ static struct qemud_server *qemudNetworkInit(struct qemud_server *server) {
|
||||||
sock = sock->next;
|
sock = sock->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_POLKIT
|
||||||
|
if (server->sysbus)
|
||||||
|
dbus_connection_unref(server->sysbus);
|
||||||
|
#endif
|
||||||
free(server);
|
free(server);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1780,6 +1804,10 @@ static int remoteConfigGetAuth(virConfPtr conf, const char *key, int *auth, cons
|
||||||
#if HAVE_SASL
|
#if HAVE_SASL
|
||||||
} else if (STREQ(p->str, "sasl")) {
|
} else if (STREQ(p->str, "sasl")) {
|
||||||
*auth = REMOTE_AUTH_SASL;
|
*auth = REMOTE_AUTH_SASL;
|
||||||
|
#endif
|
||||||
|
#if HAVE_POLKIT
|
||||||
|
} else if (STREQ(p->str, "polkit")) {
|
||||||
|
*auth = REMOTE_AUTH_POLKIT;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
qemudLog (QEMUD_ERR, "remoteReadConfigFile: %s: %s: unsupported auth %s\n", filename, key, p->str);
|
qemudLog (QEMUD_ERR, "remoteReadConfigFile: %s: %s: unsupported auth %s\n", filename, key, p->str);
|
||||||
|
@ -1816,6 +1844,13 @@ remoteReadConfigFile (struct qemud_server *server, const char *filename)
|
||||||
|
|
||||||
if (remoteConfigGetAuth(conf, "auth_unix_rw", &auth_unix_rw, filename) < 0)
|
if (remoteConfigGetAuth(conf, "auth_unix_rw", &auth_unix_rw, filename) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
#if HAVE_POLKIT
|
||||||
|
/* Change default perms to be wide-open if PolicyKit is enabled.
|
||||||
|
* Admin can always override in config file
|
||||||
|
*/
|
||||||
|
if (auth_unix_rw == REMOTE_AUTH_POLKIT)
|
||||||
|
unix_sock_rw_mask = 0777;
|
||||||
|
#endif
|
||||||
if (remoteConfigGetAuth(conf, "auth_unix_ro", &auth_unix_ro, filename) < 0)
|
if (remoteConfigGetAuth(conf, "auth_unix_ro", &auth_unix_ro, filename) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (remoteConfigGetAuth(conf, "auth_tcp", &auth_tcp, filename) < 0)
|
if (remoteConfigGetAuth(conf, "auth_tcp", &auth_tcp, filename) < 0)
|
||||||
|
|
135
qemud/remote.c
135
qemud/remote.c
|
@ -46,6 +46,11 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <fnmatch.h>
|
#include <fnmatch.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_POLKIT
|
||||||
|
#include <polkit/polkit.h>
|
||||||
|
#include <polkit-dbus/polkit-dbus.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "libvirt/virterror.h"
|
#include "libvirt/virterror.h"
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
@ -132,7 +137,8 @@ remoteDispatchClientRequest (struct qemud_server *server,
|
||||||
if (req.proc != REMOTE_PROC_AUTH_LIST &&
|
if (req.proc != REMOTE_PROC_AUTH_LIST &&
|
||||||
req.proc != REMOTE_PROC_AUTH_SASL_INIT &&
|
req.proc != REMOTE_PROC_AUTH_SASL_INIT &&
|
||||||
req.proc != REMOTE_PROC_AUTH_SASL_START &&
|
req.proc != REMOTE_PROC_AUTH_SASL_START &&
|
||||||
req.proc != REMOTE_PROC_AUTH_SASL_STEP
|
req.proc != REMOTE_PROC_AUTH_SASL_STEP &&
|
||||||
|
req.proc != REMOTE_PROC_AUTH_POLKIT
|
||||||
) {
|
) {
|
||||||
remoteDispatchError (client, &req, "authentication required");
|
remoteDispatchError (client, &req, "authentication required");
|
||||||
xdr_destroy (&xdr);
|
xdr_destroy (&xdr);
|
||||||
|
@ -2550,6 +2556,133 @@ remoteDispatchAuthSaslStep (struct qemud_server *server ATTRIBUTE_UNUSED,
|
||||||
#endif /* HAVE_SASL */
|
#endif /* HAVE_SASL */
|
||||||
|
|
||||||
|
|
||||||
|
#if HAVE_POLKIT
|
||||||
|
static int qemudGetSocketIdentity(int fd, uid_t *uid, pid_t *pid) {
|
||||||
|
#ifdef SO_PEERCRED
|
||||||
|
struct ucred cr;
|
||||||
|
unsigned int cr_len = sizeof (cr);
|
||||||
|
|
||||||
|
if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) < 0) {
|
||||||
|
qemudLog(QEMUD_ERR, "Failed to verify client credentials: %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pid = cr.pid;
|
||||||
|
*uid = cr.uid;
|
||||||
|
#else
|
||||||
|
/* XXX Many more OS support UNIX socket credentials we could port to. See dbus ....*/
|
||||||
|
#error "UNIX socket credentials not supported/implemented on this platform yet..."
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
remoteDispatchAuthPolkit (struct qemud_server *server ATTRIBUTE_UNUSED,
|
||||||
|
struct qemud_client *client,
|
||||||
|
remote_message_header *req,
|
||||||
|
void *args ATTRIBUTE_UNUSED,
|
||||||
|
remote_auth_polkit_ret *ret)
|
||||||
|
{
|
||||||
|
pid_t callerPid;
|
||||||
|
uid_t callerUid;
|
||||||
|
|
||||||
|
REMOTE_DEBUG("Start PolicyKit auth %d", client->fd);
|
||||||
|
if (client->auth != REMOTE_AUTH_POLKIT) {
|
||||||
|
qemudLog(QEMUD_ERR, "client tried invalid PolicyKit init request");
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qemudGetSocketIdentity(client->fd, &callerUid, &callerPid) < 0) {
|
||||||
|
qemudLog(QEMUD_ERR, "cannot get peer socket identity");
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only do policy checks for non-root - allow root user
|
||||||
|
through with no checks, as a fail-safe - root can easily
|
||||||
|
change policykit policy anyway, so its pointless trying
|
||||||
|
to restrict root */
|
||||||
|
if (callerUid == 0) {
|
||||||
|
qemudLog(QEMUD_INFO, "Allowing PID %d running as root", callerPid);
|
||||||
|
ret->complete = 1;
|
||||||
|
client->auth = REMOTE_AUTH_NONE;
|
||||||
|
} else {
|
||||||
|
PolKitCaller *pkcaller = NULL;
|
||||||
|
PolKitAction *pkaction = NULL;
|
||||||
|
PolKitContext *pkcontext = NULL;
|
||||||
|
PolKitError *pkerr;
|
||||||
|
PolKitResult pkresult;
|
||||||
|
DBusError err;
|
||||||
|
const char *action = client->readonly ?
|
||||||
|
"org.libvirt.unix.monitor" :
|
||||||
|
"org.libvirt.unix.manage";
|
||||||
|
|
||||||
|
qemudLog(QEMUD_INFO, "Checking PID %d running as %d", callerPid, callerUid);
|
||||||
|
dbus_error_init(&err);
|
||||||
|
if (!(pkcaller = polkit_caller_new_from_pid(server->sysbus, callerPid, &err))) {
|
||||||
|
qemudLog(QEMUD_ERR, "Failed to lookup policy kit caller: %s", err.message);
|
||||||
|
dbus_error_free(&err);
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(pkaction = polkit_action_new())) {
|
||||||
|
qemudLog(QEMUD_ERR, "Failed to create polkit action %s\n", strerror(errno));
|
||||||
|
polkit_caller_unref(pkcaller);
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
polkit_action_set_action_id(pkaction, action);
|
||||||
|
|
||||||
|
if (!(pkcontext = polkit_context_new()) ||
|
||||||
|
!polkit_context_init(pkcontext, &pkerr)) {
|
||||||
|
qemudLog(QEMUD_ERR, "Failed to create polkit context %s\n",
|
||||||
|
pkerr ? polkit_error_get_error_message(pkerr) : strerror(errno));
|
||||||
|
if (pkerr)
|
||||||
|
polkit_error_free(pkerr);
|
||||||
|
polkit_caller_unref(pkcaller);
|
||||||
|
polkit_action_unref(pkaction);
|
||||||
|
dbus_error_free(&err);
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkresult = polkit_context_can_caller_do_action(pkcontext, pkaction, pkcaller);
|
||||||
|
polkit_context_unref(pkcontext);
|
||||||
|
polkit_caller_unref(pkcaller);
|
||||||
|
polkit_action_unref(pkaction);
|
||||||
|
if (pkresult != POLKIT_RESULT_YES) {
|
||||||
|
qemudLog(QEMUD_ERR, "Policy kit denied action %s from pid %d, uid %d, result: %s\n",
|
||||||
|
action, callerPid, callerUid, polkit_result_to_string_representation(pkresult));
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
qemudLog(QEMUD_INFO, "Policy allowed action %s from pid %d, uid %d, result %s",
|
||||||
|
action, callerPid, callerUid, polkit_result_to_string_representation(pkresult));
|
||||||
|
ret->complete = 1;
|
||||||
|
client->auth = REMOTE_AUTH_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* HAVE_POLKIT */
|
||||||
|
|
||||||
|
static int
|
||||||
|
remoteDispatchAuthPolkitInit (struct qemud_server *server ATTRIBUTE_UNUSED,
|
||||||
|
struct qemud_client *client,
|
||||||
|
remote_message_header *req,
|
||||||
|
void *args ATTRIBUTE_UNUSED,
|
||||||
|
remote_auth_polkit_ret *ret ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
qemudLog(QEMUD_ERR, "client tried unsupported PolicyKit init request");
|
||||||
|
remoteDispatchFailAuth(client, req);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_POLKIT */
|
||||||
|
|
||||||
/*----- Helpers. -----*/
|
/*----- Helpers. -----*/
|
||||||
|
|
||||||
/* get_nonnull_domain and get_nonnull_network turn an on-wire
|
/* get_nonnull_domain and get_nonnull_network turn an on-wire
|
||||||
|
|
|
@ -37,6 +37,7 @@ remote_domain_set_memory_args lv_remote_domain_set_memory_args;
|
||||||
remote_domain_create_linux_args lv_remote_domain_create_linux_args;
|
remote_domain_create_linux_args lv_remote_domain_create_linux_args;
|
||||||
remote_domain_create_linux_ret lv_remote_domain_create_linux_ret;
|
remote_domain_create_linux_ret lv_remote_domain_create_linux_ret;
|
||||||
remote_domain_set_scheduler_parameters_args lv_remote_domain_set_scheduler_parameters_args;
|
remote_domain_set_scheduler_parameters_args lv_remote_domain_set_scheduler_parameters_args;
|
||||||
|
remote_auth_polkit_ret lv_remote_auth_polkit_ret;
|
||||||
remote_auth_sasl_start_args lv_remote_auth_sasl_start_args;
|
remote_auth_sasl_start_args lv_remote_auth_sasl_start_args;
|
||||||
remote_auth_sasl_start_ret lv_remote_auth_sasl_start_ret;
|
remote_auth_sasl_start_ret lv_remote_auth_sasl_start_ret;
|
||||||
remote_domain_interface_stats_args lv_remote_domain_interface_stats_args;
|
remote_domain_interface_stats_args lv_remote_domain_interface_stats_args;
|
||||||
|
|
|
@ -8,6 +8,12 @@ case REMOTE_PROC_AUTH_LIST:
|
||||||
ret = (char *) &lv_remote_auth_list_ret;
|
ret = (char *) &lv_remote_auth_list_ret;
|
||||||
memset (&lv_remote_auth_list_ret, 0, sizeof lv_remote_auth_list_ret);
|
memset (&lv_remote_auth_list_ret, 0, sizeof lv_remote_auth_list_ret);
|
||||||
break;
|
break;
|
||||||
|
case REMOTE_PROC_AUTH_POLKIT:
|
||||||
|
fn = (dispatch_fn) remoteDispatchAuthPolkit;
|
||||||
|
ret_filter = (xdrproc_t) xdr_remote_auth_polkit_ret;
|
||||||
|
ret = (char *) &lv_remote_auth_polkit_ret;
|
||||||
|
memset (&lv_remote_auth_polkit_ret, 0, sizeof lv_remote_auth_polkit_ret);
|
||||||
|
break;
|
||||||
case REMOTE_PROC_AUTH_SASL_INIT:
|
case REMOTE_PROC_AUTH_SASL_INIT:
|
||||||
fn = (dispatch_fn) remoteDispatchAuthSaslInit;
|
fn = (dispatch_fn) remoteDispatchAuthSaslInit;
|
||||||
ret_filter = (xdrproc_t) xdr_remote_auth_sasl_init_ret;
|
ret_filter = (xdrproc_t) xdr_remote_auth_sasl_init_ret;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int remoteDispatchAuthList (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_auth_list_ret *ret);
|
static int remoteDispatchAuthList (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_auth_list_ret *ret);
|
||||||
|
static int remoteDispatchAuthPolkit (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_auth_polkit_ret *ret);
|
||||||
static int remoteDispatchAuthSaslInit (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_auth_sasl_init_ret *ret);
|
static int remoteDispatchAuthSaslInit (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_auth_sasl_init_ret *ret);
|
||||||
static int remoteDispatchAuthSaslStart (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_auth_sasl_start_args *args, remote_auth_sasl_start_ret *ret);
|
static int remoteDispatchAuthSaslStart (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_auth_sasl_start_args *args, remote_auth_sasl_start_ret *ret);
|
||||||
static int remoteDispatchAuthSaslStep (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_auth_sasl_step_args *args, remote_auth_sasl_step_ret *ret);
|
static int remoteDispatchAuthSaslStep (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_auth_sasl_step_args *args, remote_auth_sasl_step_ret *ret);
|
||||||
|
|
|
@ -1308,6 +1308,15 @@ xdr_remote_auth_sasl_step_ret (XDR *xdrs, remote_auth_sasl_step_ret *objp)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_remote_auth_polkit_ret (XDR *xdrs, remote_auth_polkit_ret *objp)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!xdr_int (xdrs, &objp->complete))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
bool_t
|
bool_t
|
||||||
xdr_remote_procedure (XDR *xdrs, remote_procedure *objp)
|
xdr_remote_procedure (XDR *xdrs, remote_procedure *objp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -68,6 +68,7 @@ typedef struct remote_error remote_error;
|
||||||
enum remote_auth_type {
|
enum remote_auth_type {
|
||||||
REMOTE_AUTH_NONE = 0,
|
REMOTE_AUTH_NONE = 0,
|
||||||
REMOTE_AUTH_SASL = 1,
|
REMOTE_AUTH_SASL = 1,
|
||||||
|
REMOTE_AUTH_POLKIT = 2,
|
||||||
};
|
};
|
||||||
typedef enum remote_auth_type remote_auth_type;
|
typedef enum remote_auth_type remote_auth_type;
|
||||||
|
|
||||||
|
@ -719,6 +720,11 @@ struct remote_auth_sasl_step_ret {
|
||||||
} data;
|
} data;
|
||||||
};
|
};
|
||||||
typedef struct remote_auth_sasl_step_ret remote_auth_sasl_step_ret;
|
typedef struct remote_auth_sasl_step_ret remote_auth_sasl_step_ret;
|
||||||
|
|
||||||
|
struct remote_auth_polkit_ret {
|
||||||
|
int complete;
|
||||||
|
};
|
||||||
|
typedef struct remote_auth_polkit_ret remote_auth_polkit_ret;
|
||||||
#define REMOTE_PROGRAM 0x20008086
|
#define REMOTE_PROGRAM 0x20008086
|
||||||
#define REMOTE_PROTOCOL_VERSION 1
|
#define REMOTE_PROTOCOL_VERSION 1
|
||||||
|
|
||||||
|
@ -792,6 +798,7 @@ enum remote_procedure {
|
||||||
REMOTE_PROC_AUTH_SASL_INIT = 67,
|
REMOTE_PROC_AUTH_SASL_INIT = 67,
|
||||||
REMOTE_PROC_AUTH_SASL_START = 68,
|
REMOTE_PROC_AUTH_SASL_START = 68,
|
||||||
REMOTE_PROC_AUTH_SASL_STEP = 69,
|
REMOTE_PROC_AUTH_SASL_STEP = 69,
|
||||||
|
REMOTE_PROC_AUTH_POLKIT = 70,
|
||||||
};
|
};
|
||||||
typedef enum remote_procedure remote_procedure;
|
typedef enum remote_procedure remote_procedure;
|
||||||
|
|
||||||
|
@ -935,6 +942,7 @@ extern bool_t xdr_remote_auth_sasl_start_args (XDR *, remote_auth_sasl_start_ar
|
||||||
extern bool_t xdr_remote_auth_sasl_start_ret (XDR *, remote_auth_sasl_start_ret*);
|
extern bool_t xdr_remote_auth_sasl_start_ret (XDR *, remote_auth_sasl_start_ret*);
|
||||||
extern bool_t xdr_remote_auth_sasl_step_args (XDR *, remote_auth_sasl_step_args*);
|
extern bool_t xdr_remote_auth_sasl_step_args (XDR *, remote_auth_sasl_step_args*);
|
||||||
extern bool_t xdr_remote_auth_sasl_step_ret (XDR *, remote_auth_sasl_step_ret*);
|
extern bool_t xdr_remote_auth_sasl_step_ret (XDR *, remote_auth_sasl_step_ret*);
|
||||||
|
extern bool_t xdr_remote_auth_polkit_ret (XDR *, remote_auth_polkit_ret*);
|
||||||
extern bool_t xdr_remote_procedure (XDR *, remote_procedure*);
|
extern bool_t xdr_remote_procedure (XDR *, remote_procedure*);
|
||||||
extern bool_t xdr_remote_message_direction (XDR *, remote_message_direction*);
|
extern bool_t xdr_remote_message_direction (XDR *, remote_message_direction*);
|
||||||
extern bool_t xdr_remote_message_status (XDR *, remote_message_status*);
|
extern bool_t xdr_remote_message_status (XDR *, remote_message_status*);
|
||||||
|
@ -1054,6 +1062,7 @@ extern bool_t xdr_remote_auth_sasl_start_args ();
|
||||||
extern bool_t xdr_remote_auth_sasl_start_ret ();
|
extern bool_t xdr_remote_auth_sasl_start_ret ();
|
||||||
extern bool_t xdr_remote_auth_sasl_step_args ();
|
extern bool_t xdr_remote_auth_sasl_step_args ();
|
||||||
extern bool_t xdr_remote_auth_sasl_step_ret ();
|
extern bool_t xdr_remote_auth_sasl_step_ret ();
|
||||||
|
extern bool_t xdr_remote_auth_polkit_ret ();
|
||||||
extern bool_t xdr_remote_procedure ();
|
extern bool_t xdr_remote_procedure ();
|
||||||
extern bool_t xdr_remote_message_direction ();
|
extern bool_t xdr_remote_message_direction ();
|
||||||
extern bool_t xdr_remote_message_status ();
|
extern bool_t xdr_remote_message_status ();
|
||||||
|
|
|
@ -132,7 +132,8 @@ struct remote_error {
|
||||||
/* Authentication types available thus far.... */
|
/* Authentication types available thus far.... */
|
||||||
enum remote_auth_type {
|
enum remote_auth_type {
|
||||||
REMOTE_AUTH_NONE = 0,
|
REMOTE_AUTH_NONE = 0,
|
||||||
REMOTE_AUTH_SASL = 1
|
REMOTE_AUTH_SASL = 1,
|
||||||
|
REMOTE_AUTH_POLKIT = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -656,6 +657,10 @@ struct remote_auth_sasl_step_ret {
|
||||||
char data<REMOTE_AUTH_SASL_DATA_MAX>;
|
char data<REMOTE_AUTH_SASL_DATA_MAX>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct remote_auth_polkit_ret {
|
||||||
|
int complete;
|
||||||
|
};
|
||||||
|
|
||||||
/*----- Protocol. -----*/
|
/*----- Protocol. -----*/
|
||||||
|
|
||||||
/* Define the program number, protocol version and procedure numbers here. */
|
/* Define the program number, protocol version and procedure numbers here. */
|
||||||
|
@ -731,7 +736,8 @@ enum remote_procedure {
|
||||||
REMOTE_PROC_AUTH_LIST = 66,
|
REMOTE_PROC_AUTH_LIST = 66,
|
||||||
REMOTE_PROC_AUTH_SASL_INIT = 67,
|
REMOTE_PROC_AUTH_SASL_INIT = 67,
|
||||||
REMOTE_PROC_AUTH_SASL_START = 68,
|
REMOTE_PROC_AUTH_SASL_START = 68,
|
||||||
REMOTE_PROC_AUTH_SASL_STEP = 69
|
REMOTE_PROC_AUTH_SASL_STEP = 69,
|
||||||
|
REMOTE_PROC_AUTH_POLKIT = 70
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Custom RPC structure. */
|
/* Custom RPC structure. */
|
||||||
|
|
|
@ -115,6 +115,9 @@ static int remoteAuthenticate (virConnectPtr conn, struct private_data *priv, in
|
||||||
#if HAVE_SASL
|
#if HAVE_SASL
|
||||||
static int remoteAuthSASL (virConnectPtr conn, struct private_data *priv, int in_open);
|
static int remoteAuthSASL (virConnectPtr conn, struct private_data *priv, int in_open);
|
||||||
#endif
|
#endif
|
||||||
|
#if HAVE_POLKIT
|
||||||
|
static int remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int in_open);
|
||||||
|
#endif /* HAVE_POLKIT */
|
||||||
static void error (virConnectPtr conn, virErrorNumber code, const char *info);
|
static void error (virConnectPtr conn, virErrorNumber code, const char *info);
|
||||||
static void server_error (virConnectPtr conn, remote_error *err);
|
static void server_error (virConnectPtr conn, remote_error *err);
|
||||||
static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain);
|
static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain);
|
||||||
|
@ -2854,6 +2857,15 @@ remoteAuthenticate (virConnectPtr conn, struct private_data *priv, int in_open)
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_POLKIT
|
||||||
|
case REMOTE_AUTH_POLKIT:
|
||||||
|
if (remoteAuthPolkit(conn, priv, in_open) < 0) {
|
||||||
|
free(ret.types.types_val);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case REMOTE_AUTH_NONE:
|
case REMOTE_AUTH_NONE:
|
||||||
/* Nothing todo, hurrah ! */
|
/* Nothing todo, hurrah ! */
|
||||||
break;
|
break;
|
||||||
|
@ -3444,6 +3456,29 @@ really_write_sasl (virConnectPtr conn, struct private_data *priv,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if HAVE_POLKIT
|
||||||
|
/* Perform the PolicyKit authentication process
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int in_open)
|
||||||
|
{
|
||||||
|
remote_auth_polkit_ret ret;
|
||||||
|
|
||||||
|
remoteDebug(priv, "Client initialize PolicyKit authentication");
|
||||||
|
|
||||||
|
memset (&ret, 0, sizeof ret);
|
||||||
|
if (call (conn, priv, in_open, REMOTE_PROC_AUTH_POLKIT,
|
||||||
|
(xdrproc_t) xdr_void, (char *)NULL,
|
||||||
|
(xdrproc_t) xdr_remote_auth_polkit_ret, (char *) &ret) != 0) {
|
||||||
|
return -1; /* virError already set by call */
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteDebug(priv, "PolicyKit authentication complete");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_POLKIT */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
really_write (virConnectPtr conn, struct private_data *priv,
|
really_write (virConnectPtr conn, struct private_data *priv,
|
||||||
int in_open /* if we are in virConnectOpen */,
|
int in_open /* if we are in virConnectOpen */,
|
||||||
|
|
Loading…
Reference in New Issue