mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-03 03:25:20 +00:00
Define internal APIs for managing identities
Introduce a local object virIdentity for managing security attributes used to form a client application's identity. Instances of this object are intended to be used as if they were immutable, once created & populated with attributes Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
parent
51997e50fa
commit
3aabe27247
1
.gitignore
vendored
1
.gitignore
vendored
@ -180,6 +180,7 @@
|
|||||||
/tests/virdrivermoduletest
|
/tests/virdrivermoduletest
|
||||||
/tests/virendiantest
|
/tests/virendiantest
|
||||||
/tests/virhashtest
|
/tests/virhashtest
|
||||||
|
/tests/viridentitytest
|
||||||
/tests/virkeyfiletest
|
/tests/virkeyfiletest
|
||||||
/tests/virlockspacetest
|
/tests/virlockspacetest
|
||||||
/tests/virnet*test
|
/tests/virnet*test
|
||||||
|
@ -115,6 +115,7 @@ typedef enum {
|
|||||||
VIR_FROM_SSH = 50, /* Error from libssh2 connection transport */
|
VIR_FROM_SSH = 50, /* Error from libssh2 connection transport */
|
||||||
VIR_FROM_LOCKSPACE = 51, /* Error from lockspace */
|
VIR_FROM_LOCKSPACE = 51, /* Error from lockspace */
|
||||||
VIR_FROM_INITCTL = 52, /* Error from initctl device communication */
|
VIR_FROM_INITCTL = 52, /* Error from initctl device communication */
|
||||||
|
VIR_FROM_IDENTITY = 53, /* Error from identity code */
|
||||||
|
|
||||||
# ifdef VIR_ENUM_SENTINELS
|
# ifdef VIR_ENUM_SENTINELS
|
||||||
VIR_ERR_DOMAIN_LAST
|
VIR_ERR_DOMAIN_LAST
|
||||||
|
@ -151,6 +151,7 @@ src/util/vireventpoll.c
|
|||||||
src/util/virfile.c
|
src/util/virfile.c
|
||||||
src/util/virhash.c
|
src/util/virhash.c
|
||||||
src/util/virhook.c
|
src/util/virhook.c
|
||||||
|
src/util/viridentity.c
|
||||||
src/util/virinitctl.c
|
src/util/virinitctl.c
|
||||||
src/util/viriptables.c
|
src/util/viriptables.c
|
||||||
src/util/virjson.c
|
src/util/virjson.c
|
||||||
|
@ -83,6 +83,7 @@ UTIL_SOURCES = \
|
|||||||
util/virhash.c util/virhash.h \
|
util/virhash.c util/virhash.h \
|
||||||
util/virhashcode.c util/virhashcode.h \
|
util/virhashcode.c util/virhashcode.h \
|
||||||
util/virhook.c util/virhook.h \
|
util/virhook.c util/virhook.h \
|
||||||
|
util/viridentity.c util/viridentity.h \
|
||||||
util/virinitctl.c util/virinitctl.h \
|
util/virinitctl.c util/virinitctl.h \
|
||||||
util/viriptables.c util/viriptables.h \
|
util/viriptables.c util/viriptables.h \
|
||||||
util/virjson.c util/virjson.h \
|
util/virjson.c util/virjson.h \
|
||||||
|
@ -1288,6 +1288,13 @@ virHookInitialize;
|
|||||||
virHookPresent;
|
virHookPresent;
|
||||||
|
|
||||||
|
|
||||||
|
# util/viridentity.h
|
||||||
|
virIdentityGetAttr;
|
||||||
|
virIdentityIsEqual;
|
||||||
|
virIdentityNew;
|
||||||
|
virIdentitySetAttr;
|
||||||
|
|
||||||
|
|
||||||
# util/virinitctl.h
|
# util/virinitctl.h
|
||||||
virInitctlSetRunLevel;
|
virInitctlSetRunLevel;
|
||||||
|
|
||||||
|
@ -118,6 +118,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST,
|
|||||||
"SSH transport layer", /* 50 */
|
"SSH transport layer", /* 50 */
|
||||||
"Lock Space",
|
"Lock Space",
|
||||||
"Init control",
|
"Init control",
|
||||||
|
"Identity",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
178
src/util/viridentity.c
Normal file
178
src/util/viridentity.c
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
* viridentity.c: helper APIs for managing user identities
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
#include "viralloc.h"
|
||||||
|
#include "virerror.h"
|
||||||
|
#include "viridentity.h"
|
||||||
|
#include "virlog.h"
|
||||||
|
#include "virobject.h"
|
||||||
|
#include "virthread.h"
|
||||||
|
|
||||||
|
#define VIR_FROM_THIS VIR_FROM_IDENTITY
|
||||||
|
|
||||||
|
|
||||||
|
struct _virIdentity {
|
||||||
|
virObject parent;
|
||||||
|
|
||||||
|
char *attrs[VIR_IDENTITY_ATTR_LAST];
|
||||||
|
};
|
||||||
|
|
||||||
|
static virClassPtr virIdentityClass;
|
||||||
|
|
||||||
|
static void virIdentityDispose(void *obj);
|
||||||
|
|
||||||
|
static int virIdentityOnceInit(void)
|
||||||
|
{
|
||||||
|
if (!(virIdentityClass = virClassNew(virClassForObject(),
|
||||||
|
"virIdentity",
|
||||||
|
sizeof(virIdentity),
|
||||||
|
virIdentityDispose)))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
VIR_ONCE_GLOBAL_INIT(virIdentity)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virIdentityNew:
|
||||||
|
*
|
||||||
|
* Creates a new empty identity object. After creating, one or
|
||||||
|
* more identifying attributes should be set on the identity.
|
||||||
|
*
|
||||||
|
* Returns: a new empty identity
|
||||||
|
*/
|
||||||
|
virIdentityPtr virIdentityNew(void)
|
||||||
|
{
|
||||||
|
virIdentityPtr ident;
|
||||||
|
|
||||||
|
if (virIdentityInitialize() < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!(ident = virObjectNew(virIdentityClass)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return ident;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void virIdentityDispose(void *object)
|
||||||
|
{
|
||||||
|
virIdentityPtr ident = object;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0 ; i < VIR_IDENTITY_ATTR_LAST ; i++)
|
||||||
|
VIR_FREE(ident->attrs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virIdentitySetAttr:
|
||||||
|
* @ident: the identity to modify
|
||||||
|
* @attr: the attribute type to set
|
||||||
|
* @value: the identifying value to associate with @attr
|
||||||
|
*
|
||||||
|
* Sets an identifying attribute @attr on @ident. Each
|
||||||
|
* @attr type can only be set once.
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, or -1 on error
|
||||||
|
*/
|
||||||
|
int virIdentitySetAttr(virIdentityPtr ident,
|
||||||
|
unsigned int attr,
|
||||||
|
const char *value)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
VIR_DEBUG("ident=%p attribute=%u value=%s", ident, attr, value);
|
||||||
|
|
||||||
|
if (ident->attrs[attr]) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_DENIED, "%s",
|
||||||
|
_("Identity attribute is already set"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ident->attrs[attr] = strdup(value))) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virIdentityGetAttr:
|
||||||
|
* @ident: the identity to query
|
||||||
|
* @attr: the attribute to read
|
||||||
|
* @value: filled with the attribute value
|
||||||
|
*
|
||||||
|
* Fills @value with a pointer to the value associated
|
||||||
|
* with the identifying attribute @attr in @ident. If
|
||||||
|
* @attr is not set, then it will simply be initialized
|
||||||
|
* to NULL and considered as a successful read
|
||||||
|
*
|
||||||
|
* Returns 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int virIdentityGetAttr(virIdentityPtr ident,
|
||||||
|
unsigned int attr,
|
||||||
|
const char **value)
|
||||||
|
{
|
||||||
|
VIR_DEBUG("ident=%p attribute=%d value=%p", ident, attr, value);
|
||||||
|
|
||||||
|
*value = ident->attrs[attr];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virIdentityIsEqual:
|
||||||
|
* @identA: the first identity
|
||||||
|
* @identB: the second identity
|
||||||
|
*
|
||||||
|
* Compares every attribute in @identA and @identB
|
||||||
|
* to determine if they refer to the same identity
|
||||||
|
*
|
||||||
|
* Returns true if they are equal, false if not equal
|
||||||
|
*/
|
||||||
|
bool virIdentityIsEqual(virIdentityPtr identA,
|
||||||
|
virIdentityPtr identB)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
size_t i;
|
||||||
|
VIR_DEBUG("identA=%p identB=%p", identA, identB);
|
||||||
|
|
||||||
|
for (i = 0 ; i < VIR_IDENTITY_ATTR_LAST ; i++) {
|
||||||
|
if (STRNEQ_NULLABLE(identA->attrs[i],
|
||||||
|
identB->attrs[i]))
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
cleanup:
|
||||||
|
return ret;
|
||||||
|
}
|
60
src/util/viridentity.h
Normal file
60
src/util/viridentity.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* viridentity.h: helper APIs for managing user identities
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __VIR_IDENTITY_H__
|
||||||
|
# define __VIR_IDENTITY_H__
|
||||||
|
|
||||||
|
# include "virobject.h"
|
||||||
|
|
||||||
|
typedef struct _virIdentity virIdentity;
|
||||||
|
typedef virIdentity *virIdentityPtr;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
VIR_IDENTITY_ATTR_UNIX_USER_NAME,
|
||||||
|
VIR_IDENTITY_ATTR_UNIX_GROUP_NAME,
|
||||||
|
VIR_IDENTITY_ATTR_UNIX_PROCESS_ID,
|
||||||
|
VIR_IDENTITY_ATTR_SASL_USER_NAME,
|
||||||
|
VIR_IDENTITY_ATTR_X509_DISTINGUISHED_NAME,
|
||||||
|
VIR_IDENTITY_ATTR_SECURITY_CONTEXT,
|
||||||
|
|
||||||
|
VIR_IDENTITY_ATTR_LAST,
|
||||||
|
} virIdentityAttrType;
|
||||||
|
|
||||||
|
virIdentityPtr virIdentityNew(void);
|
||||||
|
|
||||||
|
int virIdentitySetAttr(virIdentityPtr ident,
|
||||||
|
unsigned int attr,
|
||||||
|
const char *value)
|
||||||
|
ATTRIBUTE_NONNULL(1)
|
||||||
|
ATTRIBUTE_NONNULL(3);
|
||||||
|
|
||||||
|
int virIdentityGetAttr(virIdentityPtr ident,
|
||||||
|
unsigned int attr,
|
||||||
|
const char **value)
|
||||||
|
ATTRIBUTE_NONNULL(1)
|
||||||
|
ATTRIBUTE_NONNULL(3);
|
||||||
|
|
||||||
|
bool virIdentityIsEqual(virIdentityPtr identA,
|
||||||
|
virIdentityPtr identB)
|
||||||
|
ATTRIBUTE_NONNULL(1)
|
||||||
|
ATTRIBUTE_NONNULL(2);
|
||||||
|
|
||||||
|
#endif /* __VIR_IDENTITY_H__ */
|
@ -98,6 +98,7 @@ test_programs = virshtest sockettest \
|
|||||||
virtimetest viruritest virkeyfiletest \
|
virtimetest viruritest virkeyfiletest \
|
||||||
virauthconfigtest \
|
virauthconfigtest \
|
||||||
virbitmaptest virendiantest \
|
virbitmaptest virendiantest \
|
||||||
|
viridentitytest \
|
||||||
virlockspacetest \
|
virlockspacetest \
|
||||||
virstringtest \
|
virstringtest \
|
||||||
virportallocatortest \
|
virportallocatortest \
|
||||||
@ -568,6 +569,10 @@ virstoragetest_SOURCES = \
|
|||||||
virstoragetest.c testutils.h testutils.c
|
virstoragetest.c testutils.h testutils.c
|
||||||
virstoragetest_LDADD = $(LDADDS)
|
virstoragetest_LDADD = $(LDADDS)
|
||||||
|
|
||||||
|
viridentitytest_SOURCES = \
|
||||||
|
viridentitytest.c testutils.h testutils.c
|
||||||
|
viridentitytest_LDADD = $(LDADDS)
|
||||||
|
|
||||||
virlockspacetest_SOURCES = \
|
virlockspacetest_SOURCES = \
|
||||||
virlockspacetest.c testutils.h testutils.c
|
virlockspacetest.c testutils.h testutils.c
|
||||||
virlockspacetest_LDADD = $(LDADDS)
|
virlockspacetest_LDADD = $(LDADDS)
|
||||||
|
176
tests/viridentitytest.c
Normal file
176
tests/viridentitytest.c
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "testutils.h"
|
||||||
|
|
||||||
|
#include "viridentity.h"
|
||||||
|
#include "virutil.h"
|
||||||
|
#include "virerror.h"
|
||||||
|
#include "viralloc.h"
|
||||||
|
#include "virlog.h"
|
||||||
|
|
||||||
|
#include "virlockspace.h"
|
||||||
|
|
||||||
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
||||||
|
|
||||||
|
|
||||||
|
static int testIdentityAttrs(const void *data ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
virIdentityPtr ident;
|
||||||
|
const char *val;
|
||||||
|
|
||||||
|
if (!(ident = virIdentityNew()))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virIdentitySetAttr(ident,
|
||||||
|
VIR_IDENTITY_ATTR_UNIX_USER_NAME,
|
||||||
|
"fred") < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virIdentityGetAttr(ident,
|
||||||
|
VIR_IDENTITY_ATTR_UNIX_USER_NAME,
|
||||||
|
&val) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (STRNEQ_NULLABLE(val, "fred")) {
|
||||||
|
VIR_DEBUG("Expected 'fred' got '%s'", NULLSTR(val));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virIdentityGetAttr(ident,
|
||||||
|
VIR_IDENTITY_ATTR_UNIX_GROUP_NAME,
|
||||||
|
&val) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (val != NULL) {
|
||||||
|
VIR_DEBUG("Unexpected groupname attribute");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virIdentitySetAttr(ident,
|
||||||
|
VIR_IDENTITY_ATTR_UNIX_USER_NAME,
|
||||||
|
"joe") != -1) {
|
||||||
|
VIR_DEBUG("Unexpectedly overwrote attribute");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virIdentityGetAttr(ident,
|
||||||
|
VIR_IDENTITY_ATTR_UNIX_USER_NAME,
|
||||||
|
&val) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (STRNEQ_NULLABLE(val, "fred")) {
|
||||||
|
VIR_DEBUG("Expected 'fred' got '%s'", NULLSTR(val));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
cleanup:
|
||||||
|
virObjectUnref(ident);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int testIdentityEqual(const void *data ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
virIdentityPtr identa = NULL;
|
||||||
|
virIdentityPtr identb = NULL;
|
||||||
|
|
||||||
|
if (!(identa = virIdentityNew()))
|
||||||
|
goto cleanup;
|
||||||
|
if (!(identb = virIdentityNew()))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!virIdentityIsEqual(identa, identb)) {
|
||||||
|
VIR_DEBUG("Empty identities were not equal");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virIdentitySetAttr(identa,
|
||||||
|
VIR_IDENTITY_ATTR_UNIX_USER_NAME,
|
||||||
|
"fred") < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virIdentityIsEqual(identa, identb)) {
|
||||||
|
VIR_DEBUG("Mis-matched identities should not be equal");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virIdentitySetAttr(identb,
|
||||||
|
VIR_IDENTITY_ATTR_UNIX_USER_NAME,
|
||||||
|
"fred") < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!virIdentityIsEqual(identa, identb)) {
|
||||||
|
VIR_DEBUG("Matched identities were not equal");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virIdentitySetAttr(identa,
|
||||||
|
VIR_IDENTITY_ATTR_UNIX_GROUP_NAME,
|
||||||
|
"flintstone") < 0)
|
||||||
|
goto cleanup;
|
||||||
|
if (virIdentitySetAttr(identb,
|
||||||
|
VIR_IDENTITY_ATTR_UNIX_GROUP_NAME,
|
||||||
|
"flintstone") < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!virIdentityIsEqual(identa, identb)) {
|
||||||
|
VIR_DEBUG("Matched identities were not equal");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virIdentitySetAttr(identb,
|
||||||
|
VIR_IDENTITY_ATTR_SASL_USER_NAME,
|
||||||
|
"fred@FLINTSTONE.COM") < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virIdentityIsEqual(identa, identb)) {
|
||||||
|
VIR_DEBUG("Mis-atched identities should not be equal");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
cleanup:
|
||||||
|
virObjectUnref(identa);
|
||||||
|
virObjectUnref(identb);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mymain(void)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (virtTestRun("Identity attributes ", 1, testIdentityAttrs, NULL) < 0)
|
||||||
|
ret = -1;
|
||||||
|
if (virtTestRun("Identity equality ", 1, testIdentityEqual, NULL) < 0)
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
|
return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
VIRT_TEST_MAIN(mymain)
|
Loading…
Reference in New Issue
Block a user