From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> --- 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 | 328 +++++++++++++++++++++ src/access/viraccessmanager.h | 56 ++++ src/access/viraccessvector.c | 37 +++ src/access/viraccessvector.h | 73 +++++ src/libvirt_private.syms | 22 ++ src/util/virterror.c | 9 + 15 files changed, 1382 insertions(+), 0 deletions(-) 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/viraccessvector.c create mode 100644 src/access/viraccessvector.h diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 6db31d8..74c2dec 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -85,6 +85,7 @@ typedef enum { VIR_FROM_LOCKING = 42, /* Error from lock manager */ VIR_FROM_HYPERV = 43, /* Error from Hyper-V driver */ VIR_FROM_CAPABILITIES = 44, /* Error from capabilities */ + VIR_FROM_ACCESS = 45, /* Error from access control manager */ } virErrorDomain; @@ -244,6 +245,8 @@ typedef enum { VIR_ERR_OPERATION_ABORTED = 78, /* operation on a domain was canceled/aborted by user */ VIR_ERR_INVALID_IDENTITY = 79, /* Invalid identity pointer */ + VIR_ERR_ACCESS_DENIED = 80, /* operation on the object/resource + was denied */ } virErrorNumber; /** diff --git a/po/POTFILES.in b/po/POTFILES.in index 3e8359a..0a5443f 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -4,6 +4,7 @@ daemon/remote.c daemon/remote_dispatch.h daemon/stream.c gnulib/lib/gai_strerror.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 0a1221a..0baa17d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -518,6 +518,13 @@ SECURITY_DRIVER_APPARMOR_SOURCES = \ security/security_apparmor.h security/security_apparmor.c +ACCESS_DRIVER_SOURCES = \ + access/viraccessvector.h access/viraccessvector.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 \ @@ -1101,6 +1108,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..21ae303 --- /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, + virAccessVectorConnect av); +typedef bool (*virAccessDriverCheckDomainDrv)(virAccessManagerPtr manager, + virDomainDefPtr def, + virAccessVectorDomain 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..26a14e3 --- /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, + virAccessVectorConnect av ATTRIBUTE_UNUSED) +{ + return true; +} + +static bool +virAccessDriverNopCheckDomain(virAccessManagerPtr manager ATTRIBUTE_UNUSED, + virDomainDefPtr def ATTRIBUTE_UNUSED, + virAccessVectorDomain 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..783e156 --- /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, + virAccessVectorConnect 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, + virAccessVectorDomain 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..5bb4404 --- /dev/null +++ b/src/access/viraccessmanager.c @@ -0,0 +1,328 @@ +/* + * 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 (identity) + virIdentityRef(identity); + virThreadLocalSet(&effectiveIdentity, 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 (identity) + virIdentityRef(identity); + virThreadLocalSet(&realIdentity, 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, + virAccessVectorConnect 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, + virAccessVectorDomain 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..ccbae12 --- /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/viraccessvector.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, + virAccessVectorConnect av); +bool virAccessManagerCheckDomain(virAccessManagerPtr manager, + virDomainDefPtr def, + virAccessVectorDomain av); + + +#endif /* __VIR_ACCESS_MANAGER_H__ */ diff --git a/src/access/viraccessvector.c b/src/access/viraccessvector.c new file mode 100644 index 0000000..5f40164 --- /dev/null +++ b/src/access/viraccessvector.c @@ -0,0 +1,37 @@ +/* + * viraccessvector.c: access control vectors + * + * 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 "viraccessvector.h" + + +VIR_ENUM_IMPL(virAccessVectorConnect, + VIR_ACCESS_VECTOR_CONNECT_LAST, + "getattr", "search_domains"); + +VIR_ENUM_IMPL(virAccessVectorDomain, + VIR_ACCESS_VECTOR_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/viraccessvector.h b/src/access/viraccessvector.h new file mode 100644 index 0000000..82f71cc --- /dev/null +++ b/src/access/viraccessvector.h @@ -0,0 +1,73 @@ +/* + * viraccessvector.h: access control vectors + * + * 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_VECTOR_H__ +# define __VIR_ACCESS_VECTOR_H__ + +# include "internal.h" +# include "util.h" + +typedef enum { + VIR_ACCESS_VECTOR_CONNECT_GETATTR, + VIR_ACCESS_VECTOR_CONNECT_SEARCH_DOMAINS, + + VIR_ACCESS_VECTOR_CONNECT_LAST, +} virAccessVectorConnect; + +typedef enum { + VIR_ACCESS_VECTOR_DOMAIN_GETATTR, /* Name/ID/UUID access */ + VIR_ACCESS_VECTOR_DOMAIN_READ, /* Config access */ + VIR_ACCESS_VECTOR_DOMAIN_WRITE, /* Config change */ + VIR_ACCESS_VECTOR_DOMAIN_READ_SECURE, + + VIR_ACCESS_VECTOR_DOMAIN_START, + VIR_ACCESS_VECTOR_DOMAIN_STOP, + + VIR_ACCESS_VECTOR_DOMAIN_SAVE, + VIR_ACCESS_VECTOR_DOMAIN_DELETE, + + /* Merge these 3 into 1 ? */ + VIR_ACCESS_VECTOR_DOMAIN_SHUTDOWN, + VIR_ACCESS_VECTOR_DOMAIN_REBOOT, + VIR_ACCESS_VECTOR_DOMAIN_RESET, + + VIR_ACCESS_VECTOR_DOMAIN_MIGRATE, + VIR_ACCESS_VECTOR_DOMAIN_SNAPSHOT, + VIR_ACCESS_VECTOR_DOMAIN_SUSPEND, + VIR_ACCESS_VECTOR_DOMAIN_HIBERNATE, + VIR_ACCESS_VECTOR_DOMAIN_CORE_DUMP, + + VIR_ACCESS_VECTOR_DOMAIN_INJECT_NMI, + VIR_ACCESS_VECTOR_DOMAIN_SEND_KEY, + + VIR_ACCESS_VECTOR_DOMAIN_READ_BLOCK, + VIR_ACCESS_VECTOR_DOMAIN_READ_MEM, + + VIR_ACCESS_VECTOR_DOMAIN_OPEN_GRAPHICS, + VIR_ACCESS_VECTOR_DOMAIN_OPEN_CONSOLE, + VIR_ACCESS_VECTOR_DOMAIN_SCREENSHOT, + + VIR_ACCESS_VECTOR_DOMAIN_LAST, +} virAccessVectorDomain; + +VIR_ENUM_DECL(virAccessVectorConnect); +VIR_ENUM_DECL(virAccessVectorDomain); + +#endif /* __VIR_ACCESS_VECTOR_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 363f316..829efb1 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -5,6 +5,21 @@ # Keep this file sorted by header name, then by symbols with each header. # + +# access/viraccessmanager.h +virAccessManagerInit; +virAccessManagerGetSystemIdentity; +virAccessManagerGetRealIdentity; +virAccessManagerGetEffectiveIdentity; +virAccessManagerSetRealIdentity; +virAccessManagerSetEffectiveIdentity; +virAccessManagerNew; +virAccessManagerNewStack; +virAccessManagerFree; +virAccessManagerCheckConnect; +virAccessManagerCheckDomain; + + # authhelper.h virRequestPassword; virRequestUsername; @@ -1158,6 +1173,13 @@ virUUIDGenerate; virUUIDParse; +# viraccessvector.h +virAccessVectorConnectTypeFromString; +virAccessVectorConnectTypeToString; +virAccessVectorDomainTypeFromString; +virAccessVectorDomainTypeToString; + + # viraudit.h virAuditClose; virAuditEncode; diff --git a/src/util/virterror.c b/src/util/virterror.c index 701aa2f..050f370 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -178,6 +178,9 @@ static const char *virErrorDomainName(virErrorDomain domain) { case VIR_FROM_CAPABILITIES: dom = "Capabilities "; break; + case VIR_FROM_ACCESS: + dom = "Access Manager "; + break; } return(dom); } @@ -1225,6 +1228,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.7.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list