[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH v2 2/6] Define internal APIs for managing identities



From: "Daniel P. Berrange" <berrange 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 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 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 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]