/*
* viraccessdriverstack.c: stacked access control driver
*
* Copyright (C) 2012-2013 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, see
* .
*/
#include
#include "viraccessdriverstack.h"
#include "viralloc.h"
#include "virerror.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)
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++)
virObjectUnref(priv->managers[i]);
VIR_FREE(priv->managers);
}
static int
virAccessDriverStackCheckConnect(virAccessManagerPtr manager,
const char *driverName,
virAccessPermConnect perm)
{
virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager);
int ret = 1;
size_t i;
for (i = 0; i < priv->managersLen; i++) {
int rv;
/* We do not short-circuit on first denial - always check all drivers */
rv = virAccessManagerCheckConnect(priv->managers[i], driverName, perm);
if (rv == 0 && ret != -1)
ret = 0;
else if (rv < 0)
ret = -1;
}
return ret;
}
static int
virAccessDriverStackCheckDomain(virAccessManagerPtr manager,
const char *driverName,
virDomainDefPtr domain,
virAccessPermDomain perm)
{
virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager);
int ret = 1;
size_t i;
for (i = 0; i < priv->managersLen; i++) {
int rv;
/* We do not short-circuit on first denial - always check all drivers */
rv = virAccessManagerCheckDomain(priv->managers[i], driverName, domain, perm);
if (rv == 0 && ret != -1)
ret = 0;
else if (rv < 0)
ret = -1;
}
return ret;
}
static int
virAccessDriverStackCheckInterface(virAccessManagerPtr manager,
const char *driverName,
virInterfaceDefPtr iface,
virAccessPermInterface perm)
{
virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager);
int ret = 1;
size_t i;
for (i = 0; i < priv->managersLen; i++) {
int rv;
/* We do not short-circuit on first denial - always check all drivers */
rv = virAccessManagerCheckInterface(priv->managers[i], driverName, iface, perm);
if (rv == 0 && ret != -1)
ret = 0;
else if (rv < 0)
ret = -1;
}
return ret;
}
static int
virAccessDriverStackCheckNetwork(virAccessManagerPtr manager,
const char *driverName,
virNetworkDefPtr network,
virAccessPermNetwork perm)
{
virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager);
int ret = 1;
size_t i;
for (i = 0; i < priv->managersLen; i++) {
int rv;
/* We do not short-circuit on first denial - always check all drivers */
rv = virAccessManagerCheckNetwork(priv->managers[i], driverName, network, perm);
if (rv == 0 && ret != -1)
ret = 0;
else if (rv < 0)
ret = -1;
}
return ret;
}
static int
virAccessDriverStackCheckNodeDevice(virAccessManagerPtr manager,
const char *driverName,
virNodeDeviceDefPtr nodedev,
virAccessPermNodeDevice perm)
{
virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager);
int ret = 1;
size_t i;
for (i = 0; i < priv->managersLen; i++) {
int rv;
/* We do not short-circuit on first denial - always check all drivers */
rv = virAccessManagerCheckNodeDevice(priv->managers[i], driverName, nodedev, perm);
if (rv == 0 && ret != -1)
ret = 0;
else if (rv < 0)
ret = -1;
}
return ret;
}
static int
virAccessDriverStackCheckNWFilter(virAccessManagerPtr manager,
const char *driverName,
virNWFilterDefPtr nwfilter,
virAccessPermNWFilter perm)
{
virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager);
int ret = 1;
size_t i;
for (i = 0; i < priv->managersLen; i++) {
int rv;
/* We do not short-circuit on first denial - always check all drivers */
rv = virAccessManagerCheckNWFilter(priv->managers[i], driverName, nwfilter, perm);
if (rv == 0 && ret != -1)
ret = 0;
else if (rv < 0)
ret = -1;
}
return ret;
}
static int
virAccessDriverStackCheckNWFilterBinding(virAccessManagerPtr manager,
const char *driverName,
virNWFilterBindingDefPtr binding,
virAccessPermNWFilterBinding perm)
{
virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager);
int ret = 1;
size_t i;
for (i = 0; i < priv->managersLen; i++) {
int rv;
/* We do not short-circuit on first denial - always check all drivers */
rv = virAccessManagerCheckNWFilterBinding(priv->managers[i], driverName, binding, perm);
if (rv == 0 && ret != -1)
ret = 0;
else if (rv < 0)
ret = -1;
}
return ret;
}
static int
virAccessDriverStackCheckSecret(virAccessManagerPtr manager,
const char *driverName,
virSecretDefPtr secret,
virAccessPermSecret perm)
{
virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager);
int ret = 1;
size_t i;
for (i = 0; i < priv->managersLen; i++) {
int rv;
/* We do not short-circuit on first denial - always check all drivers */
rv = virAccessManagerCheckSecret(priv->managers[i], driverName, secret, perm);
if (rv == 0 && ret != -1)
ret = 0;
else if (rv < 0)
ret = -1;
}
return ret;
}
static int
virAccessDriverStackCheckStoragePool(virAccessManagerPtr manager,
const char *driverName,
virStoragePoolDefPtr pool,
virAccessPermStoragePool perm)
{
virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager);
int ret = 1;
size_t i;
for (i = 0; i < priv->managersLen; i++) {
int rv;
/* We do not short-circuit on first denial - always check all drivers */
rv = virAccessManagerCheckStoragePool(priv->managers[i], driverName, pool, perm);
if (rv == 0 && ret != -1)
ret = 0;
else if (rv < 0)
ret = -1;
}
return ret;
}
static int
virAccessDriverStackCheckStorageVol(virAccessManagerPtr manager,
const char *driverName,
virStoragePoolDefPtr pool,
virStorageVolDefPtr vol,
virAccessPermStorageVol perm)
{
virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager);
int ret = 1;
size_t i;
for (i = 0; i < priv->managersLen; i++) {
int rv;
/* We do not short-circuit on first denial - always check all drivers */
rv = virAccessManagerCheckStorageVol(priv->managers[i], driverName, pool, vol, perm);
if (rv == 0 && ret != -1)
ret = 0;
else if (rv < 0)
ret = -1;
}
return ret;
}
virAccessDriver accessDriverStack = {
.privateDataLen = sizeof(virAccessDriverStackPrivate),
.name = "stack",
.cleanup = virAccessDriverStackCleanup,
.checkConnect = virAccessDriverStackCheckConnect,
.checkDomain = virAccessDriverStackCheckDomain,
.checkInterface = virAccessDriverStackCheckInterface,
.checkNetwork = virAccessDriverStackCheckNetwork,
.checkNodeDevice = virAccessDriverStackCheckNodeDevice,
.checkNWFilter = virAccessDriverStackCheckNWFilter,
.checkNWFilterBinding = virAccessDriverStackCheckNWFilterBinding,
.checkSecret = virAccessDriverStackCheckSecret,
.checkStoragePool = virAccessDriverStackCheckStoragePool,
.checkStorageVol = virAccessDriverStackCheckStorageVol,
};