On 05/02/2012 07:44 AM, Daniel P. Berrange wrote:
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 ++
Does it make sense to split viraccessmanager code into a separate patch?
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;
+};
Could this be called _virAccessManagerStackPrivate? See my later
comments and this may make more sense.
+
+
+int virAccessDriverStackAppend(virAccessManagerPtr manager,
+ virAccessManagerPtr child)
+{
+ virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager);
This is a driver that is calling access manager functions, which doesn't
seem right. It seems like the access manager should be able to call
down to drivers but not the other way around.
+
+ 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 = {
I noticed that virAccessDriverStackAppend() is called from the access
manager layer. At first this made me think there should be an
assignment to '.append = virAccessDriverStackAppend' here instead of
hard-coding the call in the access manager layer.
Or even better, does the driver stack really need to be a driver? Would
it make more sense to implement the driver stack entirely in the
virAccessManager layer? I think virAccessManagerCheckConnect and
virAccessManagerCheckDomain would then have to account for the stack loops.
+ .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:
Is there a leak of username, groupname, or seccontext if you goto 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 &&
Is it safe to assume mgr->drv is valid and not a bad pointer? There are
a few more places with similar code elsewhere in this patch.
+ 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;
}
--
Regards,
Corey