From: "Daniel P. Berrange" <berrange(a)redhat.com>
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(a)redhat.com>
---
.gitignore | 1 +
include/libvirt/virterror.h | 2 +
po/POTFILES.in | 1 +
src/Makefile.am | 1 +
src/libvirt_private.syms | 7 ++
src/util/virerror.c | 7 ++
src/util/viridentity.c | 178 ++++++++++++++++++++++++++++++++++++++++++++
src/util/viridentity.h | 60 +++++++++++++++
tests/Makefile.am | 5 ++
tests/viridentitytest.c | 176 +++++++++++++++++++++++++++++++++++++++++++
10 files changed, 438 insertions(+)
create mode 100644 src/util/viridentity.c
create mode 100644 src/util/viridentity.h
create mode 100644 tests/viridentitytest.c
diff --git a/.gitignore b/.gitignore
index c918372..68030d5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -180,6 +180,7 @@
/tests/virdrivermoduletest
/tests/virendiantest
/tests/virhashtest
+/tests/viridentitytest
/tests/virkeyfiletest
/tests/virlockspacetest
/tests/virnet*test
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index 4d79620..13b0abf 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -115,6 +115,7 @@ typedef enum {
VIR_FROM_SSH = 50, /* Error from libssh2 connection transport */
VIR_FROM_LOCKSPACE = 51, /* Error from lockspace */
VIR_FROM_INITCTL = 52, /* Error from initctl device communication */
+ VIR_FROM_IDENTITY = 53, /* Error from identity code */
# ifdef VIR_ENUM_SENTINELS
VIR_ERR_DOMAIN_LAST
@@ -288,6 +289,7 @@ typedef enum {
VIR_ERR_AGENT_UNRESPONSIVE = 86, /* guest agent is unresponsive,
not running or not usable */
VIR_ERR_RESOURCE_BUSY = 87, /* resource is already in use */
+ VIR_ERR_INVALID_IDENTITY = 88, /* Invalid identity pointer */
} virErrorNumber;
/**
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 5b5c3c2..07e241f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -151,6 +151,7 @@ src/util/vireventpoll.c
src/util/virfile.c
src/util/virhash.c
src/util/virhook.c
+src/util/viridentity.c
src/util/virinitctl.c
src/util/viriptables.c
src/util/virjson.c
diff --git a/src/Makefile.am b/src/Makefile.am
index a6cc839..6ba00e8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -83,6 +83,7 @@ UTIL_SOURCES = \
util/virhash.c util/virhash.h \
util/virhashcode.c util/virhashcode.h \
util/virhook.c util/virhook.h \
+ util/viridentity.c util/viridentity.h \
util/virinitctl.c util/virinitctl.h \
util/viriptables.c util/viriptables.h \
util/virjson.c util/virjson.h \
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 3243416..e636e75 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1287,6 +1287,13 @@ virHookInitialize;
virHookPresent;
+# util/viridentity.h
+virIdentityGetAttr;
+virIdentityIsEqual;
+virIdentityNew;
+virIdentitySetAttr;
+
+
# util/virinitctl.h
virInitctlSetRunLevel;
diff --git a/src/util/virerror.c b/src/util/virerror.c
index 40c3b25..8cb8548 100644
--- a/src/util/virerror.c
+++ b/src/util/virerror.c
@@ -118,6 +118,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST,
"SSH transport layer", /* 50 */
"Lock Space",
"Init control",
+ "Identity",
)
@@ -1213,6 +1214,12 @@ virErrorMsg(virErrorNumber error, const char *info)
else
errmsg = _("resource busy %s");
break;
+ case VIR_ERR_INVALID_IDENTITY:
+ if (info == NULL)
+ errmsg = _("invalid identity");
+ else
+ errmsg = _("invalid identity %s");
+ break;
}
return errmsg;
}
diff --git a/src/util/viridentity.c b/src/util/viridentity.c
new file mode 100644
index 0000000..7ebf851
--- /dev/null
+++ b/src/util/viridentity.c
@@ -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 1 if they are equal, 0 if not equal or -1 on error
+ */
+int virIdentityIsEqual(virIdentityPtr identA,
+ virIdentityPtr identB)
+{
+ int ret = 0;
+ 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 = 1;
+cleanup:
+ return ret;
+}
diff --git a/src/util/viridentity.h b/src/util/viridentity.h
new file mode 100644
index 0000000..5992b1a
--- /dev/null
+++ b/src/util/viridentity.h
@@ -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);
+
+int virIdentityIsEqual(virIdentityPtr identA,
+ virIdentityPtr identB)
+ ATTRIBUTE_NONNULL(1)
+ ATTRIBUTE_NONNULL(2);
+
+#endif /* __VIR_IDENTITY_H__ */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d3a7868..6bb946a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -98,6 +98,7 @@ test_programs = virshtest sockettest \
virtimetest viruritest virkeyfiletest \
virauthconfigtest \
virbitmaptest virendiantest \
+ viridentitytest \
virlockspacetest \
virstringtest \
virportallocatortest \
@@ -568,6 +569,10 @@ virstoragetest_SOURCES = \
virstoragetest.c testutils.h testutils.c
virstoragetest_LDADD = $(LDADDS)
+viridentitytest_SOURCES = \
+ viridentitytest.c testutils.h testutils.c
+viridentitytest_LDADD = $(LDADDS)
+
virlockspacetest_SOURCES = \
virlockspacetest.c testutils.h testutils.c
virlockspacetest_LDADD = $(LDADDS)
diff --git a/tests/viridentitytest.c b/tests/viridentitytest.c
new file mode 100644
index 0000000..adb4f7d
--- /dev/null
+++ b/tests/viridentitytest.c
@@ -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(a)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 (STRNEQ_NULLABLE(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 no 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(a)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)
--
1.8.1.4