From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> 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@xxxxxxxxxx> --- .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@xxxxxxxxxx> + */ + +#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@xxxxxxxxxxxxxx") < 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list