From: "Daniel P. Berrange" <berrange(a)redhat.com>
---
include/libvirt/virterror.h | 3 +
po/POTFILES.in | 1 +
src/Makefile.am | 16 +
src/access/apis.txt | 577 +++++++++++++++++++++++++++++++++++++
src/access/viraccessdriver.h | 51 ++++
src/access/viraccessdrivernop.c | 44 +++
src/access/viraccessdrivernop.h | 28 ++
src/access/viraccessdriverstack.c | 105 +++++++
src/access/viraccessdriverstack.h | 32 ++
src/access/viraccessmanager.c | 338 ++++++++++++++++++++++
src/access/viraccessmanager.h | 56 ++++
src/access/viraccessperm.c | 37 +++
src/access/viraccessperm.h | 73 +++++
src/libvirt_private.syms | 21 ++
src/util/virterror.c | 9 +
15 files changed, 1391 insertions(+)
create mode 100644 src/access/apis.txt
create mode 100644 src/access/viraccessdriver.h
create mode 100644 src/access/viraccessdrivernop.c
create mode 100644 src/access/viraccessdrivernop.h
create mode 100644 src/access/viraccessdriverstack.c
create mode 100644 src/access/viraccessdriverstack.h
create mode 100644 src/access/viraccessmanager.c
create mode 100644 src/access/viraccessmanager.h
create mode 100644 src/access/viraccessperm.c
create mode 100644 src/access/viraccessperm.h
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index e44390e..1daba04 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -88,6 +88,7 @@ typedef enum {
VIR_FROM_URI = 45, /* Error from URI handling */
VIR_FROM_AUTH = 46, /* Error from auth handling */
VIR_FROM_DBUS = 47, /* Error from DBus */
+ VIR_FROM_ACCESS = 48, /* Error from access control manager */
} virErrorDomain;
@@ -252,6 +253,8 @@ typedef enum {
VIR_ERR_OVERFLOW = 82, /* integer overflow */
VIR_ERR_BLOCK_COPY_ACTIVE = 83, /* action prevented by block copy job */
VIR_ERR_INVALID_IDENTITY = 84, /* Invalid identity pointer */
+ VIR_ERR_ACCESS_DENIED = 85, /* operation on the object/resource
+ was denied */
} virErrorNumber;
/**
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 4ea544b..f898887 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/viraccessmanager.c
src/conf/cpu_conf.c
src/conf/domain_conf.c
src/conf/domain_event.c
diff --git a/src/Makefile.am b/src/Makefile.am
index e48dfa5..0293562 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -531,6 +531,13 @@ SECURITY_DRIVER_APPARMOR_SOURCES = \
security/security_apparmor.h security/security_apparmor.c
+ACCESS_DRIVER_SOURCES = \
+ access/viraccessperm.h access/viraccessperm.c \
+ access/viraccessmanager.h access/viraccessmanager.c \
+ access/viraccessdriver.h \
+ access/viraccessdrivernop.h access/viraccessdrivernop.c \
+ access/viraccessdriverstack.h access/viraccessdriverstack.c
+
NODE_DEVICE_DRIVER_SOURCES = \
node_device/node_device_driver.c \
node_device/node_device_driver.h \
@@ -1115,6 +1122,15 @@ libvirt_driver_security_la_CFLAGS += $(APPARMOR_CFLAGS)
libvirt_driver_security_la_LIBADD += $(APPARMOR_LIBS)
endif
+libvirt_driver_access_la_SOURCES = $(ACCESS_DRIVER_SOURCES)
+noinst_LTLIBRARIES += libvirt_driver_access.la
+libvirt_la_BUILT_LIBADD += libvirt_driver_access.la
+libvirt_driver_access_la_CFLAGS = \
+ -I@top_srcdir@/src/conf $(AM_CFLAGS)
+libvirt_driver_access_la_LDFLAGS = $(AM_LDFLAGS)
+libvirt_driver_access_la_LIBADD =
+
+
# Add all conditional sources just in case...
EXTRA_DIST += \
$(TEST_DRIVER_SOURCES) \
diff --git a/src/access/apis.txt b/src/access/apis.txt
new file mode 100644
index 0000000..16cc49c
--- /dev/null
+++ b/src/access/apis.txt
@@ -0,0 +1,577 @@
+
+Non-driver based APIs
+
+
+virConnCopyLastError:
+virResetError:
+virResetLastError:
+virSaveLastError:
+virSetErrorFunc:
+virConnGetLastError:
+virConnResetLastError:
+virConnSetErrorFunc:
+virCopyLastError:
+virDefaultErrorFunc:
+virFreeError:
+virGetLastError:
+
+virInitialize:
+virConnectClose:
+virConnectGetLibVersion:
+virGetVersion:
+virConnectGetVersion:
+virConnectGetType:
+virConnectGetURI:
+
+
+virConnectRef:
+virDomainRef:
+virInterfaceRef:
+virNetworkRef:
+virNodeDeviceRef:
+virNWFilterRef:
+virSecretRef:
+virStoragePoolRef:
+virStorageVolRef:
+virStreamRef:
+
+virIdentityFree:
+virDomainFree:
+virDomainSnapshotFree:
+virInterfaceFree:
+virNetworkFree:
+virNodeDeviceFree:
+virNWFilterFree:
+virSecretFree:
+virStoragePoolFree:
+virStorageVolFree:
+virStreamFree:
+
+virDomainGetConnect:
+virInterfaceGetConnect:
+virDomainSnapshotGetConnect:
+virNetworkGetConnect:
+virSecretGetConnect:
+virStoragePoolGetConnect:
+virStorageVolGetConnect:
+virDomainSnapshotGetDomain:
+
+virEventAddHandle:
+virEventAddTimeout:
+virEventRegisterDefaultImpl:
+virEventRegisterImpl:
+virEventRemoveHandle:
+virEventRemoveTimeout:
+virEventRunDefaultImpl:
+virEventUpdateHandle:
+virEventUpdateTimeout:
+
+
+virConnectBaselineCPU:
+
+ - No state access
+
+virConnectCompareCPU:
+
+ - Access host CPU
+
+virConnectGetCapabilities:
+
+ - Access host CPU, emulators, NUMA
+
+virConnectGetHostname:
+
+ - hostname resolve
+
+virConnectGetIdentity:
+
+ - No state
+
+virConnectGetMaxVcpus:
+
+ - Hypercall
+
+virConnectGetSysinfo:
+
+ - Sysfs / dmidecode ? (cached from capabilities)
+
+virConnectIsAlive:
+
+ - Driver check
+
+virConnectIsEncrypted:
+virConnectIsSecure:
+
+ - Property lookup
+
+virConnectOpen:
+virConnectOpenAuth:
+virConnectOpenReadOnly:
+
+ - RPC layer
+
+virConnectSetIdentity:
+
+ - RPC layer
+
+virConnectSetKeepAlive:
+
+ - RPC layer
+
+virNodeGetCellsFreeMemory:
+
+ - NUMA props
+
+virNodeGetCPUStats:
+
+ - Cgroups
+
+virNodeGetFreeMemory:
+
+ - NUMA props
+
+virNodeGetInfo:
+
+ - NUMA / sysfs
+
+virNodeGetMemoryStats:
+
+ - CGroups
+
+virNodeGetSecurityModel:
+
+ - Capabilities
+
+virNodeSuspendForDuration:
+
+ - PM utils invoke
+
+
+
+virConnectNumOfDefinedDomains:
+virConnectNumOfDomains:
+virConnectListDefinedDomains:
+virConnectListDomains:
+
+ - 'search_domains' on libvirtd
+ - 'getattr' on each domain
+
+
+virConnectDomainEventDeregister:
+virConnectDomainEventDeregisterAny:
+virConnectDomainEventRegister:
+virConnectDomainEventRegisterAny:
+
+ - 'monitor' on domain
+
+virConnectDomainXMLFromNative:
+virConnectDomainXMLToNative:
+
+ - 'domain_xml' on libvirtd
+
+virDomainAbortJob:
+
+ - 'abort_job'
+
+virDomainBlockJobAbort:
+
+ - 'abort_block_job'
+
+virDomainBlockJobSetSpeed:
+
+ - 'setattr_block_job'
+
+virDomainBlockPeek:
+
+ - 'block_peek'
+
+virDomainBlockPull:
+
+ - 'block_pull'
+ - 'create_block_job'
+
+virDomainBlockResize:
+
+ - 'block_resize'
+
+virDomainBlockStats:
+virDomainBlockStatsFlags:
+
+ - 'read'
+
+virDomainCoreDump:
+
+ - 'coredump'
+
+virDomainCreate:
+virDomainCreateLinux:
+virDomainCreateWithFlags:
+
+ - 'start'
+
+virDomainCreateXML:
+
+ - 'start' + 'write'
+
+virDomainDefineXML:
+
+ - 'save' + 'write'
+
+virDomainDestroy:
+virDomainDestroyFlags:
+
+ - 'stop'
+
+
+virDomainGetID:
+virDomainGetName:
+virDomainGetUUID:
+virDomainGetUUIDString:
+virDomainLookupByUUIDString:
+
+ - Outside driver
+
+virDomainLookupByID:
+virDomainLookupByName:
+virDomainLookupByUUID:
+
+ - getattr
+
+virDomainGetAutostart:
+virDomainGetBlkioParameters:
+virDomainGetBlockInfo:
+virDomainGetBlockIoTune:
+virDomainGetBlockJobInfo:
+virDomainGetControlInfo:
+virDomainGetInfo:
+virDomainGetInterfaceParameters:
+virDomainGetJobInfo:
+virDomainGetMaxMemory:
+virDomainGetMaxVcpus:
+virDomainGetMemoryParameters:
+virDomainGetNumaParameters:
+virDomainGetOSType:
+virDomainGetSchedulerParameters:
+virDomainGetSchedulerParametersFlags:
+virDomainGetSchedulerType:
+virDomainGetSecurityLabel:
+virDomainGetState:
+virDomainGetVcpuPinInfo:
+virDomainGetVcpus:
+virDomainGetVcpusFlags:
+virDomainGetXMLDesc:
+virDomainHasCurrentSnapshot:
+virDomainHasManagedSaveImage:
+virDomainInterfaceStats:
+virDomainIsActive:
+virDomainIsPersistent:
+virDomainIsUpdated:
+virDomainMemoryStats:
+
+ - 'read'
+
+virDomainInjectNMI:
+
+ - inject_nmi
+
+
+virDomainManagedSave:
+
+ - save_create
+
+virDomainManagedSaveRemove:
+
+ - save_delete
+
+virDomainMemoryPeek:
+
+ - memory_peek
+
+
+virDomainMigrate:
+virDomainMigrate2:
+virDomainMigrateGetMaxSpeed:
+virDomainMigrateSetMaxDowntime:
+virDomainMigrateSetMaxSpeed:
+virDomainMigrateToURI:
+virDomainMigrateToURI2:
+
+ - migrate
+
+virDomainOpenConsole:
+
+ - open_console
+
+virDomainOpenGraphics:
+
+ - open_graphics
+
+virDomainPinVcpu:
+virDomainPinVcpuFlags:
+
+ - write ?
+
+virDomainReboot:
+
+ - reboot
+
+virDomainReset:
+
+ - reset
+
+virDomainRestore:
+virDomainRestoreFlags:
+
+ - restore
+ - start
+
+virDomainResume:
+
+ - resume
+
+virDomainRevertToSnapshot:
+
+ - snapshot_revert
+
+virDomainSave:
+virDomainSaveFlags:
+
+ - stop
+ - save
+
+virDomainSaveImageDefineXML:
+
+ - save_write (setattr ?)
+
+virDomainSaveImageGetXMLDesc:
+
+ - save_getattr
+
+
+virDomainScreenshot:
+
+ - screenshot
+
+virDomainSendKey:
+
+ - sendkey
+
+virDomainSetAutostart:
+virDomainSetBlkioParameters:
+virDomainSetBlockIoTune:
+virDomainSetInterfaceParameters:
+virDomainSetMaxMemory:
+virDomainSetMemory:
+virDomainSetMemoryFlags:
+virDomainSetMemoryParameters:
+virDomainSetNumaParameters:
+virDomainSetSchedulerParameters:
+virDomainSetSchedulerParametersFlags:
+virDomainSetVcpus:
+virDomainSetVcpusFlags:
+virDomainAttachDevice:
+virDomainAttachDeviceFlags:
+virDomainUpdateDeviceFlags:
+virDomainDetachDevice:
+virDomainDetachDeviceFlags:
+
+
+ - write (+ possible save)
+
+virDomainShutdown:
+
+ - shutdown
+
+virDomainSnapshotCreateXML:
+
+ - snapshot_create
+
+virDomainSnapshotCurrent:
+
+ - snapshot_getattr (or getattr ?)
+
+virDomainSnapshotDelete:
+
+ - snapshot_delete
+
+virDomainSnapshotGetName:
+virDomainSnapshotGetParent:
+virDomainSnapshotGetXMLDesc:
+
+ - snapshot_getattr
+
+virDomainSnapshotListChildrenNames:
+virDomainSnapshotListNames:
+
+ - snapshot_search
+ - Filter on snapshot_getattr
+
+virDomainSnapshotLookupByName:
+
+ - snapshot_getattr
+
+virDomainSnapshotNum:
+virDomainSnapshotNumChildren:
+
+ - snapshot_search
+ - Filter on snapshot_getattr
+
+virDomainSuspend:
+
+ - suspend
+
+virDomainUndefine:
+virDomainUndefineFlags:
+
+ - delete
+
+
+
+virConnectNumOfDefinedInterfaces:
+virConnectNumOfInterfaces:
+virConnectListDefinedInterfaces:
+virConnectListInterfaces:
+virInterfaceChangeBegin:
+virInterfaceChangeCommit:
+virInterfaceChangeRollback:
+virInterfaceCreate:
+virInterfaceDefineXML:
+virInterfaceDestroy:
+virInterfaceGetMACString:
+virInterfaceGetName:
+virInterfaceGetXMLDesc:
+virInterfaceIsActive:
+virInterfaceLookupByMACString:
+virInterfaceLookupByName:
+virInterfaceUndefine:
+
+
+virConnectNumOfDefinedNetworks:
+virConnectNumOfNetworks:
+virConnectListDefinedNetworks:
+virConnectListNetworks:
+virNetworkCreate:
+virNetworkCreateXML:
+virNetworkDefineXML:
+virNetworkDestroy:
+virNetworkGetAutostart:
+virNetworkGetBridgeName:
+virNetworkGetName:
+virNetworkGetUUID:
+virNetworkGetUUIDString:
+virNetworkGetXMLDesc:
+virNetworkIsActive:
+virNetworkIsPersistent:
+virNetworkLookupByName:
+virNetworkLookupByUUID:
+virNetworkLookupByUUIDString:
+virNetworkSetAutostart:
+virNetworkUndefine:
+
+
+
+virNodeDeviceCreateXML:
+virNodeDeviceDestroy:
+virNodeDeviceDettach:
+virNodeDeviceGetName:
+virNodeDeviceGetParent:
+virNodeDeviceGetXMLDesc:
+virNodeDeviceListCaps:
+virNodeDeviceLookupByName:
+virNodeDeviceNumOfCaps:
+virNodeDeviceReAttach:
+virNodeDeviceReset:
+virNodeListDevices:
+virNodeNumOfDevices:
+
+
+
+virConnectNumOfNWFilters:
+virConnectListNWFilters:
+virNWFilterDefineXML:
+virNWFilterGetName:
+virNWFilterGetUUID:
+virNWFilterGetUUIDString:
+virNWFilterGetXMLDesc:
+virNWFilterLookupByName:
+virNWFilterLookupByUUID:
+virNWFilterLookupByUUIDString:
+virNWFilterUndefine:
+
+
+
+virConnectNumOfSecrets:
+virConnectListSecrets:
+virSecretDefineXML:
+virSecretGetUsageID:
+virSecretGetUsageType:
+virSecretGetUUID:
+virSecretGetUUIDString:
+virSecretGetValue:
+virSecretGetXMLDesc:
+virSecretLookupByUsage:
+virSecretLookupByUUID:
+virSecretLookupByUUIDString:
+virSecretSetValue:
+virSecretUndefine:
+
+
+
+virConnectNumOfDefinedStoragePools:
+virConnectNumOfStoragePools:
+virConnectListDefinedStoragePools:
+virConnectListStoragePools:
+virConnectFindStoragePoolSources:
+virStoragePoolBuild:
+virStoragePoolCreate:
+virStoragePoolCreateXML:
+virStoragePoolDefineXML:
+virStoragePoolDelete:
+virStoragePoolDestroy:
+virStoragePoolGetAutostart:
+virStoragePoolGetInfo:
+virStoragePoolGetName:
+virStoragePoolGetUUID:
+virStoragePoolGetUUIDString:
+virStoragePoolGetXMLDesc:
+virStoragePoolIsActive:
+virStoragePoolIsPersistent:
+virStoragePoolListVolumes:
+virStoragePoolLookupByName:
+virStoragePoolLookupByUUID:
+virStoragePoolLookupByUUIDString:
+virStoragePoolLookupByVolume:
+virStoragePoolNumOfVolumes:
+virStoragePoolRefresh:
+virStoragePoolSetAutostart:
+virStoragePoolUndefine:
+
+
+
+virStorageVolCreateXML:
+virStorageVolCreateXMLFrom:
+virStorageVolDelete:
+virStorageVolDownload:
+virStorageVolGetInfo:
+virStorageVolGetKey:
+virStorageVolGetName:
+virStorageVolGetPath:
+virStorageVolGetXMLDesc:
+virStorageVolLookupByKey:
+virStorageVolLookupByName:
+virStorageVolLookupByPath:
+virStorageVolUpload:
+virStorageVolWipe:
+
+
+
+virStreamAbort:
+virStreamEventAddCallback:
+virStreamEventRemoveCallback:
+virStreamEventUpdateCallback:
+virStreamFinish:
+virStreamNew:
+virStreamRecv:
+virStreamRecvAll:
+virStreamSend:
+virStreamSendAll:
diff --git a/src/access/viraccessdriver.h b/src/access/viraccessdriver.h
new file mode 100644
index 0000000..ae09162
--- /dev/null
+++ b/src/access/viraccessdriver.h
@@ -0,0 +1,51 @@
+/*
+ * viraccessdriver.h: 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_H__
+# define __VIR_ACCESS_DRIVER_H__
+
+# include "conf/domain_conf.h"
+# include "access/viraccessmanager.h"
+
+typedef bool (*virAccessDriverCheckConnectDrv)(virAccessManagerPtr manager,
+ virAccessPermConnect av);
+typedef bool (*virAccessDriverCheckDomainDrv)(virAccessManagerPtr manager,
+ virDomainDefPtr def,
+ virAccessPermDomain av);
+
+typedef int (*virAccessDriverSetupDrv)(virAccessManagerPtr manager);
+typedef void (*virAccessDriverCleanupDrv)(virAccessManagerPtr manager);
+
+typedef struct _virAccessDriver virAccessDriver;
+typedef virAccessDriver *virAccessDriverPtr;
+
+struct _virAccessDriver {
+ size_t privateDataLen;
+ const char *name;
+
+ virAccessDriverSetupDrv setup;
+ virAccessDriverCleanupDrv cleanup;
+
+ virAccessDriverCheckConnectDrv checkConnect;
+ virAccessDriverCheckDomainDrv checkDomain;
+};
+
+
+#endif /* __VIR_ACCESS_DRIVER_H__ */
diff --git a/src/access/viraccessdrivernop.c b/src/access/viraccessdrivernop.c
new file mode 100644
index 0000000..7ba0719
--- /dev/null
+++ b/src/access/viraccessdrivernop.c
@@ -0,0 +1,44 @@
+/*
+ * viraccessdrivernop.c: no-op access control driver
+ *
+ * Copyright (C) 2011 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/viraccessdrivernop.h"
+
+static bool
+virAccessDriverNopCheckConnect(virAccessManagerPtr manager ATTRIBUTE_UNUSED,
+ virAccessPermConnect av ATTRIBUTE_UNUSED)
+{
+ return true;
+}
+
+static bool
+virAccessDriverNopCheckDomain(virAccessManagerPtr manager ATTRIBUTE_UNUSED,
+ virDomainDefPtr def ATTRIBUTE_UNUSED,
+ virAccessPermDomain av ATTRIBUTE_UNUSED)
+{
+ return true;
+}
+
+virAccessDriver accessDriverNop = {
+ .name = "none",
+ .checkConnect = virAccessDriverNopCheckConnect,
+ .checkDomain = virAccessDriverNopCheckDomain,
+};
diff --git a/src/access/viraccessdrivernop.h b/src/access/viraccessdrivernop.h
new file mode 100644
index 0000000..a3d9be3
--- /dev/null
+++ b/src/access/viraccessdrivernop.h
@@ -0,0 +1,28 @@
+/*
+ * viraccessdrivernop.h: no-op access control driver
+ *
+ * Copyright (C) 2011 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_NOP_H__
+# define __VIR_ACCESS_DRIVER_NOP_H__
+
+# include "access/viraccessdriver.h"
+
+extern virAccessDriver accessDriverNop;
+
+#endif /* __VIR_ACCESS_DRIVER_NOP_H__ */
diff --git a/src/access/viraccessdriverstack.c b/src/access/viraccessdriverstack.c
new file mode 100644
index 0000000..48aaafd
--- /dev/null
+++ b/src/access/viraccessdriverstack.c
@@ -0,0 +1,105 @@
+/*
+ * viraccessdriverstack.c: stacked 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/viraccessdriverstack.h"
+#include "memory.h"
+#include "virterror_internal.h"
+
+#define VIR_FROM_THIS VIR_FROM_ACCESS
+
+typedef struct _virAccessDriverStackPrivate virAccessDriverStackPrivate;
+typedef virAccessDriverStackPrivate *virAccessDriverStackPrivatePtr;
+
+struct _virAccessDriverStackPrivate {
+ virAccessManagerPtr *managers;
+ size_t managersLen;
+};
+
+
+int virAccessDriverStackAppend(virAccessManagerPtr manager,
+ virAccessManagerPtr child)
+{
+ virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager);
+
+ if (VIR_EXPAND_N(priv->managers, priv->managersLen, 1) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ priv->managers[priv->managersLen-1] = child;
+
+ return 0;
+}
+
+
+static void virAccessDriverStackCleanup(virAccessManagerPtr manager)
+{
+ virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager);
+ size_t i;
+
+ for (i = 0 ; i < priv->managersLen ; i++) {
+ virAccessManagerFree(priv->managers[i]);
+ }
+ VIR_FREE(priv->managers);
+}
+
+
+static bool
+virAccessDriverStackCheckConnect(virAccessManagerPtr manager,
+ virAccessPermConnect av)
+{
+ virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager);
+ bool ret = true;
+ size_t i;
+
+ for (i = 0 ; i < priv->managersLen ; i++) {
+ /* We do not short-circuit on first denial - always check all drivers */
+ if (!virAccessManagerCheckConnect(priv->managers[i], av))
+ ret = false;
+ }
+
+ return ret;
+}
+
+static bool
+virAccessDriverStackCheckDomain(virAccessManagerPtr manager,
+ virDomainDefPtr def,
+ virAccessPermDomain av)
+{
+ virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager);
+ bool ret = true;
+ size_t i;
+
+ for (i = 0 ; i < priv->managersLen ; i++) {
+ /* We do not short-circuit on first denial - always check all drivers */
+ if (!virAccessManagerCheckDomain(priv->managers[i], def, av))
+ ret = false;
+ }
+
+ return ret;
+}
+
+virAccessDriver accessDriverStack = {
+ .cleanup = virAccessDriverStackCleanup,
+ .checkConnect = virAccessDriverStackCheckConnect,
+ .checkDomain = virAccessDriverStackCheckDomain,
+};
diff --git a/src/access/viraccessdriverstack.h b/src/access/viraccessdriverstack.h
new file mode 100644
index 0000000..8ab3a0d
--- /dev/null
+++ b/src/access/viraccessdriverstack.h
@@ -0,0 +1,32 @@
+/*
+ * viraccessdriverstack.h: stacked 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_STACK_H__
+# define __VIR_ACCESS_DRIVER_STACK_H__
+
+# include "access/viraccessdriver.h"
+
+
+int virAccessDriverStackAppend(virAccessManagerPtr manager,
+ virAccessManagerPtr child);
+
+extern virAccessDriver accessDriverStack;
+
+#endif /* __VIR_ACCESS_DRIVER_STACK_H__ */
diff --git a/src/access/viraccessmanager.c b/src/access/viraccessmanager.c
new file mode 100644
index 0000000..4e77bd6
--- /dev/null
+++ b/src/access/viraccessmanager.c
@@ -0,0 +1,338 @@
+/*
+ * viraccessmanager.c: access control manager
+ *
+ * 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 "viraccessmanager.h"
+#include "memory.h"
+#include "virterror_internal.h"
+#include "threads.h"
+#if HAVE_SELINUX
+# include <selinux/selinux.h>
+#endif
+#include "access/viraccessdrivernop.h"
+#include "access/viraccessdriverstack.h"
+#include "logging.h"
+
+#define VIR_FROM_THIS VIR_FROM_ACCESS
+#define virAccessError(code, ...) \
+ virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \
+ __FUNCTION__, __LINE__, __VA_ARGS__)
+
+static volatile bool onceInitErr = false;
+static virOnceControl onceInit = VIR_ONCE_CONTROL_INITIALIZER;
+static virThreadLocal realIdentity;
+static virThreadLocal effectiveIdentity;
+
+struct _virAccessManager {
+ virAccessDriverPtr drv;
+};
+
+
+static void virAccessManagerOnceInit(void)
+{
+ if (virThreadLocalInit(&realIdentity,
+ (virThreadLocalCleanup)virIdentityFree) < 0)
+ onceInitErr = true;
+ if (virThreadLocalInit(&effectiveIdentity,
+ (virThreadLocalCleanup)virIdentityFree) < 0)
+ onceInitErr = true;
+}
+
+static bool virAccessManagerInit(void)
+{
+ if (virOnce(&onceInit, virAccessManagerOnceInit) < 0 ||
+ onceInitErr) {
+ virReportSystemError(errno, "%s",
+ _("Failed to initialize access manager"));
+ return false;
+ }
+
+ return true;
+}
+
+virIdentityPtr virAccessManagerGetSystemIdentity(void)
+{
+ char *username = NULL;
+ char *groupname = NULL;
+ char *seccontext = NULL;
+ virIdentityPtr ret = NULL;
+ gid_t gid = getgid();
+ uid_t uid = getuid();
+#if HAVE_SELINUX
+ security_context_t con;
+#endif
+
+ if (!(username = virGetUserName(uid)))
+ goto cleanup;
+ if (!(groupname = virGetGroupName(gid)))
+ goto cleanup;
+
+#if HAVE_SELINUX
+ if (getcon(&con) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Unable to lookup SELinux process context"));
+ goto cleanup;
+ }
+ seccontext = strdup(con);
+ freecon(con);
+ if (!seccontext) {
+ virReportOOMError();
+ goto cleanup;
+ }
+#endif
+
+ if (!(ret = virIdentityNew()))
+ goto cleanup;
+
+ if (username &&
+ virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_USER_NAME, username) < 0)
+ goto error;
+ if (groupname &&
+ virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_GROUP_NAME, groupname) < 0)
+ goto error;
+ if (seccontext &&
+ virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_SECURITY_CONTEXT, seccontext) < 0)
+ goto error;
+
+cleanup:
+ VIR_FREE(username);
+ VIR_FREE(groupname);
+ VIR_FREE(seccontext);
+ return ret;
+
+error:
+ virIdentityFree(ret);
+ ret = NULL;
+ goto cleanup;
+}
+
+virIdentityPtr virAccessManagerGetEffectiveIdentity(void)
+{
+ virIdentityPtr ret;
+
+ if (!virAccessManagerInit())
+ return NULL;
+
+ ret = virThreadLocalGet(&effectiveIdentity);
+ virIdentityRef(ret);
+ return ret;
+}
+
+int virAccessManagerSetEffectiveIdentity(virIdentityPtr identity)
+{
+ virIdentityPtr old;
+
+ if (!virAccessManagerInit())
+ return -1;
+
+ old = virThreadLocalGet(&effectiveIdentity);
+ if (old)
+ virIdentityFree(old);
+
+ if (virThreadLocalSet(&effectiveIdentity, identity) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Unable to set thread local identity"));
+ return -1;
+ }
+
+ if (identity)
+ virIdentityRef(identity);
+ return 0;
+}
+
+virIdentityPtr virAccessManagerGetRealIdentity(void)
+{
+ virIdentityPtr ret;
+
+ if (!virAccessManagerInit())
+ return NULL;
+
+ ret = virThreadLocalGet(&realIdentity);
+ virIdentityRef(ret);
+ return ret;
+}
+
+int virAccessManagerSetRealIdentity(virIdentityPtr identity)
+{
+ virIdentityPtr old;
+
+ if (!virAccessManagerInit())
+ return -1;
+
+ old = virThreadLocalGet(&realIdentity);
+ if (old)
+ virIdentityFree(old);
+
+ if (virThreadLocalSet(&realIdentity, identity) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Unable to set thread local identity"));
+ return -1;
+ }
+
+ if (identity)
+ virIdentityRef(identity);
+ return 0;
+}
+
+
+static virAccessManagerPtr virAccessManagerNewDriver(virAccessDriverPtr drv)
+{
+ virAccessManagerPtr mgr;
+
+ if (VIR_ALLOC_VAR(mgr, char, drv->privateDataLen) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ mgr->drv = drv;
+
+ if (mgr->drv->setup &&
+ mgr->drv->setup(mgr) < 0) {
+ VIR_FREE(mgr);
+ return NULL;
+ }
+
+ return mgr;
+}
+
+
+static virAccessDriverPtr accessDrivers[] = {
+ &accessDriverNop,
+};
+
+
+static virAccessDriverPtr virAccessManagerFindDriver(const char *name)
+{
+ size_t i;
+ for (i = 0 ; i < ARRAY_CARDINALITY(accessDrivers) ; i++) {
+ if (STREQ(name, accessDrivers[i]->name))
+ return accessDrivers[i];
+ }
+
+ return NULL;
+}
+
+
+virAccessManagerPtr virAccessManagerNew(const char *name)
+{
+ virAccessDriverPtr drv = virAccessManagerFindDriver(name);
+ if (!drv)
+ return NULL;
+
+ return virAccessManagerNewDriver(drv);
+}
+
+
+virAccessManagerPtr virAccessManagerNewStack(const char **names,
+ size_t namesLen)
+{
+ virAccessManagerPtr manager = virAccessManagerNewDriver(&accessDriverStack);
+ size_t i;
+
+ if (!manager)
+ return NULL;
+
+ for (i = 0 ; i < namesLen ; i++) {
+ virAccessManagerPtr child = virAccessManagerNew(names[i]);
+
+ if (!child)
+ goto error;
+
+ if (virAccessDriverStackAppend(manager, child) < 0) {
+ virAccessManagerFree(child);
+ goto error;
+ }
+ }
+
+ return manager;
+
+error:
+ virAccessManagerFree(manager);
+ return NULL;
+}
+
+
+void *virAccessManagerGetPrivateData(virAccessManagerPtr mgr)
+{
+ /* This accesses the memory just beyond mgr, which was allocated
+ * via VIR_ALLOC_VAR earlier. */
+ return mgr + 1;
+}
+
+
+void virAccessManagerFree(virAccessManagerPtr mgr)
+{
+ if (!mgr)
+ return;
+
+ if (mgr->drv->cleanup)
+ mgr->drv->cleanup(mgr);
+
+ VIR_FREE(mgr);
+}
+
+
+/* Standard security practice is to not tell the caller *why*
+ * they were denied access. So this method takes the real
+ * libvirt errors & replaces it with a generic error. Fortunately
+ * the daemon logs will still contain the original error message
+ * should the admin need to debug things
+ */
+static bool
+virAccessManagerSanitizeError(bool ret)
+{
+ if (!ret) {
+ virResetLastError();
+ virAccessError(VIR_ERR_ACCESS_DENIED, NULL);
+ }
+
+ return ret;
+}
+
+bool virAccessManagerCheckConnect(virAccessManagerPtr manager,
+ virAccessPermConnect av)
+{
+ bool ret = true;
+ VIR_DEBUG("manager=%p driver=%s av=%d",
+ manager, manager->drv->name, av);
+
+ if (manager->drv->checkConnect &&
+ !manager->drv->checkConnect(manager, av))
+ ret = false;
+
+ return virAccessManagerSanitizeError(ret);
+}
+
+
+bool virAccessManagerCheckDomain(virAccessManagerPtr manager,
+ virDomainDefPtr def,
+ virAccessPermDomain av)
+{
+ bool ret = true;
+ VIR_DEBUG("manager=%p driver=%s def=%p av=%d",
+ manager, manager->drv->name, def, av);
+
+ if (manager->drv->checkDomain &&
+ !manager->drv->checkDomain(manager, def, av))
+ ret = false;
+
+ return virAccessManagerSanitizeError(ret);
+}
diff --git a/src/access/viraccessmanager.h b/src/access/viraccessmanager.h
new file mode 100644
index 0000000..b7e19b5
--- /dev/null
+++ b/src/access/viraccessmanager.h
@@ -0,0 +1,56 @@
+/*
+ * viraccessmanager.h: access control manager
+ *
+ * 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_MANAGER_H__
+# define __VIR_ACCESS_MANAGER_H__
+
+# include "rpc/virnetserverclient.h"
+# include "conf/domain_conf.h"
+# include "access/viraccessperm.h"
+
+virIdentityPtr virAccessManagerGetClientIdentity(virNetServerClientPtr client);
+virIdentityPtr virAccessManagerGetSystemIdentity(void);
+
+virIdentityPtr virAccessManagerGetEffectiveIdentity(void);
+int virAccessManagerSetEffectiveIdentity(virIdentityPtr identity);
+
+virIdentityPtr virAccessManagerGetRealIdentity(void);
+int virAccessManagerSetRealIdentity(virIdentityPtr identity);
+
+typedef struct _virAccessManager virAccessManager;
+typedef virAccessManager *virAccessManagerPtr;
+
+virAccessManagerPtr virAccessManagerNew(const char *name);
+virAccessManagerPtr virAccessManagerNewStack(const char **names,
+ size_t namesLen);
+
+
+void *virAccessManagerGetPrivateData(virAccessManagerPtr manager);
+void virAccessManagerFree(virAccessManagerPtr manager);
+
+
+bool virAccessManagerCheckConnect(virAccessManagerPtr manager,
+ virAccessPermConnect av);
+bool virAccessManagerCheckDomain(virAccessManagerPtr manager,
+ virDomainDefPtr def,
+ virAccessPermDomain av);
+
+
+#endif /* __VIR_ACCESS_MANAGER_H__ */
diff --git a/src/access/viraccessperm.c b/src/access/viraccessperm.c
new file mode 100644
index 0000000..7ccded5
--- /dev/null
+++ b/src/access/viraccessperm.c
@@ -0,0 +1,37 @@
+/*
+ * viraccessperm.c: access control permissions
+ *
+ * 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 "viraccessperm.h"
+
+
+VIR_ENUM_IMPL(virAccessPermConnect,
+ VIR_ACCESS_PERM_CONNECT_LAST,
+ "getattr", "search_domains");
+
+VIR_ENUM_IMPL(virAccessPermDomain,
+ VIR_ACCESS_PERM_DOMAIN_LAST,
+ "getattr", "read", "write",
"read_secure",
+ "start", "stop", "save", "delete",
+ "shutdown", "reboot", "reset",
+ "migrate", "snapshot", "suspend",
"hibernate", "core_dump",
+ "inject_nmi", "send_key", "read_block",
"read_mem",
+ "open_graphics", "open_console",
"screenshot");
diff --git a/src/access/viraccessperm.h b/src/access/viraccessperm.h
new file mode 100644
index 0000000..83b17ad
--- /dev/null
+++ b/src/access/viraccessperm.h
@@ -0,0 +1,73 @@
+/*
+ * viraccessperm.h: access control permissions
+ *
+ * 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_PERM_H__
+# define __VIR_ACCESS_PERM_H__
+
+# include "internal.h"
+# include "util.h"
+
+typedef enum {
+ VIR_ACCESS_PERM_CONNECT_GETATTR,
+ VIR_ACCESS_PERM_CONNECT_SEARCH_DOMAINS,
+
+ VIR_ACCESS_PERM_CONNECT_LAST,
+} virAccessPermConnect;
+
+typedef enum {
+ VIR_ACCESS_PERM_DOMAIN_GETATTR, /* Name/ID/UUID access */
+ VIR_ACCESS_PERM_DOMAIN_READ, /* Config access */
+ VIR_ACCESS_PERM_DOMAIN_WRITE, /* Config change */
+ VIR_ACCESS_PERM_DOMAIN_READ_SECURE,
+
+ VIR_ACCESS_PERM_DOMAIN_START,
+ VIR_ACCESS_PERM_DOMAIN_STOP,
+
+ VIR_ACCESS_PERM_DOMAIN_SAVE,
+ VIR_ACCESS_PERM_DOMAIN_DELETE,
+
+ /* Merge these 3 into 1 ? */
+ VIR_ACCESS_PERM_DOMAIN_SHUTDOWN,
+ VIR_ACCESS_PERM_DOMAIN_REBOOT,
+ VIR_ACCESS_PERM_DOMAIN_RESET,
+
+ VIR_ACCESS_PERM_DOMAIN_MIGRATE,
+ VIR_ACCESS_PERM_DOMAIN_SNAPSHOT,
+ VIR_ACCESS_PERM_DOMAIN_SUSPEND,
+ VIR_ACCESS_PERM_DOMAIN_HIBERNATE,
+ VIR_ACCESS_PERM_DOMAIN_CORE_DUMP,
+
+ VIR_ACCESS_PERM_DOMAIN_INJECT_NMI,
+ VIR_ACCESS_PERM_DOMAIN_SEND_KEY,
+
+ VIR_ACCESS_PERM_DOMAIN_READ_BLOCK,
+ VIR_ACCESS_PERM_DOMAIN_READ_MEM,
+
+ VIR_ACCESS_PERM_DOMAIN_OPEN_GRAPHICS,
+ VIR_ACCESS_PERM_DOMAIN_OPEN_CONSOLE,
+ VIR_ACCESS_PERM_DOMAIN_SCREENSHOT,
+
+ VIR_ACCESS_PERM_DOMAIN_LAST,
+} virAccessPermDomain;
+
+VIR_ENUM_DECL(virAccessPermConnect);
+VIR_ENUM_DECL(virAccessPermDomain);
+
+#endif /* __VIR_ACCESS_PERM_H__ */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 391c977..ca60eb3 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1181,6 +1181,27 @@ virAuthConfigNew;
virAuthConfigNewData;
+# viraccessmanager.h
+virAccessManagerInit;
+virAccessManagerGetSystemIdentity;
+virAccessManagerGetRealIdentity;
+virAccessManagerGetEffectiveIdentity;
+virAccessManagerSetRealIdentity;
+virAccessManagerSetEffectiveIdentity;
+virAccessManagerNew;
+virAccessManagerNewStack;
+virAccessManagerFree;
+virAccessManagerCheckConnect;
+virAccessManagerCheckDomain;
+
+
+# viraccessvector.h
+virAccessVectorConnectTypeFromString;
+virAccessVectorConnectTypeToString;
+virAccessVectorDomainTypeFromString;
+virAccessVectorDomainTypeToString;
+
+
# viraudit.h
virAuditClose;
virAuditEncode;
diff --git a/src/util/virterror.c b/src/util/virterror.c
index 33ef713..e60a008 100644
--- a/src/util/virterror.c
+++ b/src/util/virterror.c
@@ -187,6 +187,9 @@ static const char *virErrorDomainName(virErrorDomain domain) {
case VIR_FROM_DBUS:
dom = "DBus ";
break;
+ case VIR_FROM_ACCESS:
+ dom = "Access Manager ";
+ break;
}
return dom;
}
@@ -1265,6 +1268,12 @@ virErrorMsg(virErrorNumber error, const char *info)
else
errmsg = _("invalid identity pointer in %s");
break;
+ case VIR_ERR_ACCESS_DENIED:
+ if (info == NULL)
+ errmsg = _("access denied");
+ else
+ errmsg = _("access denied: %s");
+ break;
}
return errmsg;
}
--
1.7.10