Index: qemud/Makefile.am =================================================================== RCS file: /data/cvs/libvirt/qemud/Makefile.am,v retrieving revision 1.29 diff -u -p -r1.29 Makefile.am --- qemud/Makefile.am 27 Jun 2007 00:12:29 -0000 1.29 +++ qemud/Makefile.am 8 Aug 2007 04:10:44 -0000 @@ -18,9 +18,10 @@ libvirtd_CFLAGS = \ -DSYSCONF_DIR="\"$(sysconfdir)\"" \ -DQEMUD_PID_FILE="\"$(QEMUD_PID_FILE)\"" \ -DREMOTE_PID_FILE="\"$(REMOTE_PID_FILE)\"" \ - -DGETTEXT_PACKAGE=\"$(PACKAGE)\" + -DGETTEXT_PACKAGE=\"$(PACKAGE)\" \ + $(POLKIT_CFLAGS) $(POLKIT_DBUS_CFLAGS) -libvirtd_LDFLAGS = $(WARN_CFLAGS) $(LIBXML_LIBS) +libvirtd_LDFLAGS = $(WARN_CFLAGS) $(LIBXML_LIBS) $(POLKIT_LIBS) $(POLKIT_DBUS_LIBS) libvirtd_DEPENDENCIES = ../src/libvirt.la libvirtd_LDADD = ../src/libvirt.la @@ -53,6 +54,13 @@ EXTRA_DIST = libvirtd.init.in libvirtd.s remote_dispatch_localvars.h \ remote_dispatch_proc_switch.h +if HAVE_POLICY_KIT +policydir = $(datadir)/PolicyKit/policy +policy_DATA = libvirtd.policy +endif +EXTRA_DIST += libvirtd.policy + + .x.c: rm -f $@ rpcgen -c -o $@ $< Index: qemud/internal.h =================================================================== RCS file: /data/cvs/libvirt/qemud/internal.h,v retrieving revision 1.33 diff -u -p -r1.33 internal.h --- qemud/internal.h 7 Aug 2007 13:02:35 -0000 1.33 +++ qemud/internal.h 8 Aug 2007 04:10:45 -0000 @@ -33,6 +33,10 @@ #include "remote_protocol.h" #include "../config.h" +#ifdef HAVE_POLICY_KIT +#include "dbus/dbus.h" +#endif + #ifdef __GNUC__ #ifdef HAVE_ANSIDECL_H #include @@ -60,6 +64,14 @@ typedef enum { } qemudLogPriority; +enum libvirtd_auth { + LIBVIRTD_AUTH_NONE, + LIBVIRTD_AUTH_TLS, +#ifdef HAVE_POLICY_KIT + LIBVIRTD_AUTH_POLICYKIT, +#endif +}; + enum qemud_mode { QEMUD_MODE_RX_HEADER, QEMUD_MODE_RX_PAYLOAD, @@ -84,8 +96,8 @@ struct qemud_client { struct sockaddr_storage addr; socklen_t addrlen; - /* If set, TLS is required on this socket. */ - int tls; + /* Required auth mode for incoming connections */ + int auth; gnutls_session_t session; enum qemud_tls_direction direction; @@ -111,8 +123,8 @@ struct qemud_client { struct qemud_socket { int fd; int readonly; - /* If set, TLS is required on this socket. */ - int tls; + /* Required auth mode for incoming connections */ + int auth; struct qemud_socket *next; }; @@ -126,6 +138,9 @@ struct qemud_server { int sigread; char logDir[PATH_MAX]; unsigned int shutdown : 1; +#ifdef HAVE_POLICY_KIT + DBusConnection *sysbus; +#endif }; void qemudLog(int priority, const char *fmt, ...) Index: qemud/libvirtd.policy =================================================================== RCS file: qemud/libvirtd.policy diff -N qemud/libvirtd.policy --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ qemud/libvirtd.policy 8 Aug 2007 04:10:45 -0000 @@ -0,0 +1,41 @@ + + + + + + + Virtualization + + + Monitor local virtualized systems + System policy prevents monitoring local virtualized systems + + yes + yes + + + + + Manage local virtualized systems + System policy prevents managing local virtualized systems + + no + auth_admin + + + + + Index: qemud/qemud.c =================================================================== RCS file: /data/cvs/libvirt/qemud/qemud.c,v retrieving revision 1.56 diff -u -p -r1.56 qemud.c --- qemud/qemud.c 7 Aug 2007 13:24:22 -0000 1.56 +++ qemud/qemud.c 8 Aug 2007 04:10:45 -0000 @@ -57,6 +57,11 @@ #include "../src/conf.h" #include "event.h" +#ifdef HAVE_POLICY_KIT +#include +#include +#endif + static int godaemon = 0; /* -d: Be a daemon */ static int verbose = 0; /* -v: Verbose mode */ static int timeout = -1; /* -t: Shutdown timeout */ @@ -448,6 +453,9 @@ static int qemudListenUnix(struct qemud_ } sock->readonly = readonly; +#ifdef HAVE_POLICY_KIT + sock->auth = LIBVIRTD_AUTH_POLICYKIT; +#endif if ((sock->fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { qemudLog(QEMUD_ERR, "Failed to create socket: %s", @@ -465,11 +473,14 @@ static int qemudListenUnix(struct qemud_ if (addr.sun_path[0] == '@') addr.sun_path[0] = '\0'; - +#ifdef HAVE_POLICY_KIT + oldmask = umask(~(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)); +#else if (readonly) oldmask = umask(~(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)); else oldmask = umask(~(S_IRUSR | S_IWUSR)); +#endif if (bind(sock->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { qemudLog(QEMUD_ERR, "Failed to bind socket to '%s': %s", path, strerror(errno)); @@ -559,7 +570,7 @@ remoteMakeSockets (int *fds, int max_fds static int remoteListenTCP (struct qemud_server *server, const char *port, - int tls) + int auth) { int fds[2]; int nfds = 0; @@ -584,7 +595,7 @@ remoteListenTCP (struct qemud_server *se server->nsockets++; sock->fd = fds[i]; - sock->tls = tls; + sock->auth = auth; if (qemudSetCloseExec(sock->fd) < 0 || qemudSetNonBlock(sock->fd) < 0) @@ -667,6 +678,9 @@ static struct qemud_server *qemudInitial struct qemud_server *server; char sockname[PATH_MAX]; char roSockname[PATH_MAX]; +#ifdef HAVE_POLICY_KIT + DBusError err; +#endif if (!(server = calloc(1, sizeof(struct qemud_server)))) { qemudLog(QEMUD_ERR, "Failed to allocate struct qemud_server"); @@ -687,6 +701,16 @@ static struct qemud_server *qemudInitial if (roSockname[0] != '\0' && qemudListenUnix(server, roSockname, 1) < 0) goto cleanup; +#ifdef HAVE_POLICY_KIT + dbus_error_init(&err); + server->sysbus = dbus_bus_get(DBUS_BUS_SYSTEM, &err); + if (!(server->sysbus)) { + qemudLog(QEMUD_ERR, "Failed to connect to system bus: %s", err.message); + dbus_error_free(&err); + goto cleanup; + } +#endif + __virEventRegisterImpl(virEventAddHandleImpl, virEventRemoveHandleImpl, virEventAddTimeoutImpl, @@ -695,14 +719,14 @@ static struct qemud_server *qemudInitial virStateInitialize(); if (ipsock) { - if (listen_tcp && remoteListenTCP (server, tcp_port, 0) < 0) + if (listen_tcp && remoteListenTCP (server, tcp_port, LIBVIRTD_AUTH_NONE) < 0) goto cleanup; if (listen_tls) { if (remoteInitializeGnuTLS () < 0) goto cleanup; - if (remoteListenTCP (server, tls_port, 1) < 0) + if (remoteListenTCP (server, tls_port, LIBVIRTD_AUTH_TLS) < 0) goto cleanup; } } @@ -717,6 +741,9 @@ static struct qemud_server *qemudInitial sock = sock->next; } +#ifdef HAVE_POLICY_KTI + dbus_connection_unref(server->sysbus); +#endif free(server); } return NULL; @@ -945,6 +972,7 @@ static int qemudDispatchServer(struct qe socklen_t addrlen = (socklen_t) (sizeof addr); struct qemud_client *client; int no_slow_start = 1; + int ret; if ((fd = accept(sock->fd, (struct sockaddr *)&addr, &addrlen)) < 0) { if (errno == EAGAIN) @@ -967,19 +995,96 @@ static int qemudDispatchServer(struct qe client->magic = QEMUD_CLIENT_MAGIC; client->fd = fd; client->readonly = sock->readonly; - client->tls = sock->tls; + client->auth = sock->auth; memcpy (&client->addr, &addr, sizeof addr); client->addrlen = addrlen; - if (!client->tls) { + switch (client->auth) { +#ifdef HAVE_POLICY_KIT + case LIBVIRTD_AUTH_POLICYKIT: + { + PolKitCaller *pkcaller = NULL; + PolKitAction *pkaction = NULL; + PolKitContext *pkcontext = NULL; + PolKitError *pkerr; + PolKitResult pkresult; + const char *action = sock->readonly ? + "libvirtd-local-monitor" : + "libvirtd-local-manage"; + pid_t callerPid; + DBusError err; +#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)); + close(fd); + free(client); + return -1; + } + callerPid = cr.pid; +#else + /* XXX Many more OS support UNIX socket credentials we could port to ....*/ +#error "UNIX socket credentials not supported/implemeneted on this platform" +#endif + + 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); + close(fd); + free(client); + return -1; + } + + if (!(pkaction = polkit_action_new())) { + qemudLog(QEMUD_ERR, "Failed to create polkit action %s\n", strerror(errno)); + polkit_caller_unref(pkcaller); + close(fd); + free(client); + return -1; + } + 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); + close(fd); + free(client); + return -1; + } + + 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, result: %s\n", + action, callerPid, polkit_result_to_string_representation(pkresult)); + close(fd); + free(client); + return -1; + } + } + /* Allowed by policy kit, so fallthrough to generic setup... */ +#endif + + case LIBVIRTD_AUTH_NONE: client->mode = QEMUD_MODE_RX_HEADER; client->bufferLength = QEMUD_PKT_HEADER_XDR_LEN; if (qemudRegisterClientEvent (server, client, 0) < 0) goto cleanup; - } else { - int ret; + break; + case LIBVIRTD_AUTH_TLS: client->session = remoteInitializeTLSSession (); if (client->session == NULL) goto cleanup; @@ -1009,6 +1114,13 @@ static int qemudDispatchServer(struct qe gnutls_strerror (ret)); goto cleanup; } + break; + + default: + qemudLog(QEMUD_ERR, "Unknown authentication scheme configured: %d\n", sock->auth); + close(fd); + free(client); + return -1; } client->next = server->clients; @@ -1048,7 +1160,8 @@ static void qemudDispatchClientFailure(s if (client->conn) virConnectClose(client->conn); - if (client->tls && client->session) gnutls_deinit (client->session); + if (client->auth == LIBVIRTD_AUTH_TLS && client->session) + gnutls_deinit (client->session); close(client->fd); free(client); } @@ -1065,7 +1178,7 @@ static int qemudClientRead(struct qemud_ /*qemudDebug ("qemudClientRead: len = %d", len);*/ - if (!client->tls) { + if (client->auth != LIBVIRTD_AUTH_TLS) { if ((ret = read (client->fd, data, len)) <= 0) { if (ret == 0 || errno != EAGAIN) { if (ret != 0) @@ -1133,7 +1246,8 @@ static void qemudDispatchClientRead(stru client->mode = QEMUD_MODE_RX_PAYLOAD; client->bufferLength = h.length; - if (client->tls) client->direction = QEMUD_TLS_DIRECTION_READ; + if (client->auth == LIBVIRTD_AUTH_TLS) + client->direction = QEMUD_TLS_DIRECTION_READ; /* Note that we don't reset bufferOffset here because we want * to retain the whole message, including header. */ @@ -1221,7 +1335,7 @@ static int qemudClientWrite(struct qemud data = client->buffer + client->bufferOffset; len = client->bufferLength - client->bufferOffset; - if (!client->tls) { + if (client->auth != LIBVIRTD_AUTH_TLS) { if ((ret = write(client->fd, data, len)) == -1) { if (errno != EAGAIN) { qemudLog (QEMUD_ERR, "write: %s", strerror (errno)); @@ -1260,7 +1374,8 @@ static void qemudDispatchClientWrite(str client->mode = QEMUD_MODE_RX_HEADER; client->bufferLength = QEMUD_PKT_HEADER_XDR_LEN; client->bufferOffset = 0; - if (client->tls) client->direction = QEMUD_TLS_DIRECTION_READ; + if (client->auth == LIBVIRTD_AUTH_TLS) + client->direction = QEMUD_TLS_DIRECTION_READ; if (qemudRegisterClientEvent (server, client, 1) < 0) qemudDispatchClientFailure (server, client); @@ -1329,7 +1444,7 @@ static int qemudRegisterClientEvent(stru if (virEventRemoveHandleImpl(client->fd) < 0) return -1; - if (client->tls) { + if (client->auth == LIBVIRTD_AUTH_TLS) { if (virEventAddHandleImpl(client->fd, (client->direction ? POLLOUT : POLLIN) | POLLERR | POLLHUP, Index: qemud/remote.c =================================================================== RCS file: /data/cvs/libvirt/qemud/remote.c,v retrieving revision 1.6 diff -u -p -r1.6 remote.c --- qemud/remote.c 24 Jul 2007 14:21:03 -0000 1.6 +++ qemud/remote.c 8 Aug 2007 04:10:45 -0000 @@ -266,7 +266,8 @@ remoteDispatchClientRequest (struct qemu client->mode = QEMUD_MODE_TX_PACKET; client->bufferLength = len; client->bufferOffset = 0; - if (client->tls) client->direction = QEMUD_TLS_DIRECTION_WRITE; + if (client->auth == LIBVIRTD_AUTH_TLS) + client->direction = QEMUD_TLS_DIRECTION_WRITE; } /* An error occurred during the dispatching process itself (ie. not @@ -360,7 +361,8 @@ remoteDispatchError (struct qemud_client client->mode = QEMUD_MODE_TX_PACKET; client->bufferLength = len; client->bufferOffset = 0; - if (client->tls) client->direction = QEMUD_TLS_DIRECTION_WRITE; + if (client->auth == LIBVIRTD_AUTH_TLS) + client->direction = QEMUD_TLS_DIRECTION_WRITE; } /*----- Functions. -----*/ Index: configure.in =================================================================== RCS file: /data/cvs/libvirt/configure.in,v retrieving revision 1.80 diff -u -p -r1.80 configure.in --- configure.in 7 Aug 2007 13:02:35 -0000 1.80 +++ configure.in 8 Aug 2007 04:11:09 -0000 @@ -12,6 +12,8 @@ LIBVIRT_VERSION_INFO=`expr $LIBVIRT_MAJO LIBVIRT_VERSION_NUMBER=`expr $LIBVIRT_MAJOR_VERSION \* 1000000 + $LIBVIRT_MINOR_VERSION \* 1000 + $LIBVIRT_MICRO_VERSION` +POLKIT_REQUIRED=0.5 + if test -f CVS/Entries; then extra=`grep ChangeLog CVS/Entries | grep -v LIBVIR | sed -e s\%/ChangeLog/1\.%% -e s\%/.*$%%` echo extra=$extra @@ -72,15 +74,15 @@ AC_SUBST(HTML_DIR) dnl Allow to build without Xen, QEMU/KVM, test or remote driver AC_ARG_WITH(xen, -[ --with-xen add XEN support (on)]) +[ --with-xen add XEN support (on)],[],[with_xen=yes]) AC_ARG_WITH(qemu, -[ --with-qemu add QEMU/KVM support (on)]) +[ --with-qemu add QEMU/KVM support (on)],[],[with_qemu=yes]) AC_ARG_WITH(openvz, -[ --with-openvz add OpenVZ support (off)]) +[ --with-openvz add OpenVZ support (off)],[],[with_openvz=no]) AC_ARG_WITH(test, -[ --with-test add test driver support (on)]) +[ --with-test add test driver support (on)],[],[with_test=yes]) AC_ARG_WITH(remote, -[ --with-remote add remote driver support (on)]) +[ --with-remote add remote driver support (on)],[],[with_remote=yes]) dnl dnl specific tests to setup DV devel environments with debug etc ... @@ -95,7 +97,7 @@ AC_SUBST(STATIC_BINARIES) dnl --enable-debug=(yes|no) AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug=no/yes], - [enable debugging output])) + [enable debugging output]),[],[enable_debug=no]) if test x"$enable_debug" = x"yes"; then AC_DEFINE(ENABLE_DEBUG, [], [whether debugging is enabled]) fi @@ -424,6 +426,36 @@ AC_SUBST(PYTHON_VERSION) AC_SUBST(PYTHON_INCLUDES) AC_SUBST(PYTHON_SITE_PACKAGES) +PKG_PROG_PKG_CONFIG() + +AC_ARG_WITH(policykit, + [ --with-policykit use policy kit for local authentication (on)], + [], + [with_policykit=check]) + +if test "$with_policykit" = "check"; then + AC_MSG_CHECKING([if PolicyKit >= $POLKIT_REQUIRED is available]) + PKG_CHECK_EXISTS(polkit >= $POLKIT_REQUIRED, [have_policykit=yes], [have_policykit=no]) + AC_MSG_RESULT([$have_policykit]) + with_policykit="$have_policykit" +fi + +if test "$with_policykit" = "yes" ; then + PKG_CHECK_MODULES(POLKIT, polkit >= $POLKIT_REQUIRED) + PKG_CHECK_MODULES(POLKIT_DBUS, polkit-dbus >= $POLKIT_REQUIRED) + AC_DEFINE_UNQUOTED(HAVE_POLICY_KIT, 1, [whether policy kit is used for UNIX socket auth]) +else + POLKIT_CFLAGS= + POLKIT_LIBS= + POLKIT_DBUS_CFLAGS= + POLKIT_DBUS_LIBS= +fi +AM_CONDITIONAL(HAVE_POLICY_KIT, [test "$with_policykit" = "yes"]) +AC_SUBST(POLKIT_CFLAGS) +AC_SUBST(POLKIT_LIBS) +AC_SUBST(POLKIT_DBUS_CFLAGS) +AC_SUBST(POLKIT_DBUS_LIBS) + AC_MSG_CHECKING([whether this host is running a Xen kernel]) RUNNING_XEN= if test -d /proc/sys/xen @@ -490,3 +522,19 @@ AC_OUTPUT(Makefile src/Makefile include/ tests/xmconfigdata/Makefile \ tests/xencapsdata/Makefile \ tests/virshdata/Makefile tests/confdata/Makefile) + +echo +echo "Drivers:" +echo " Xen: $with_xen" +echo " QEMU: $with_qemu" +echo " Test: $with_test" +echo " OpenVZ: $with_openvz" +echo " Remote: $with_remote" +echo +echo "General features:" +echo " Debug: $enable_debug" +if test "$with_remote" = "yes"; then + echo + echo "Remote driver features:" + echo " PolicyKit: $with_policykit" +fi