summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stefw@collabora.co.uk>2011-06-20 21:17:03 +0200
committerStef Walter <stefw@collabora.co.uk>2011-07-06 12:49:26 +0200
commitf1ca5d5b57909534d8b21f9be455c94ca57e6636 (patch)
tree1b0e46bea3f2d2af81525c4aa11914d1c099b995
parent0a793a9e462727f434f6283a712b37ab30df5e95 (diff)
downloadp11-kit-f1ca5d5b57909534d8b21f9be455c94ca57e6636.tar.gz
Implement support for registering and calling pinfile callbacks
* These are callbacks that hanlde the pinfile part of a PKCS#11 URI. * One library can register a callback that another can then call in a thread-safe and simple fashion.
-rw-r--r--.gitignore2
-rw-r--r--p11-kit/Makefile.am3
-rw-r--r--p11-kit/pin.c332
-rw-r--r--p11-kit/pin.h85
-rw-r--r--p11-kit/ptr-array.c150
-rw-r--r--p11-kit/ptr-array.h61
-rw-r--r--tests/Makefile.am12
-rw-r--r--tests/pin-test.c237
-rw-r--r--tests/ptr-array-test.c259
9 files changed, 1140 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index a844dce..c5a95f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -67,6 +67,8 @@ temp.txt
/tests/coverage
/tests/coverage.info
/tests/hash-test
+/tests/pin-test
+/tests/ptr-array-test
/tests/conf-test
/tests/uri-test
diff --git a/p11-kit/Makefile.am b/p11-kit/Makefile.am
index 9afc6b6..9366a05 100644
--- a/p11-kit/Makefile.am
+++ b/p11-kit/Makefile.am
@@ -7,6 +7,7 @@ incdir = $(includedir)/p11-kit-1/p11-kit
inc_HEADERS = \
p11-kit.h \
+ pin.h \
uri.h \
pkcs11.h
@@ -16,8 +17,10 @@ MODULE_SRCS = \
debug.c debug.h \
hash.c hash.h \
modules.c \
+ pin.c \
proxy.c \
private.h \
+ ptr-array.c ptr-array.h \
messages.c \
uri.c \
$(inc_HEADERS)
diff --git a/p11-kit/pin.c b/p11-kit/pin.c
new file mode 100644
index 0000000..328785f
--- /dev/null
+++ b/p11-kit/pin.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@collabora.co.uk>
+ */
+
+#include "config.h"
+
+#define DEBUG_FLAG DEBUG_PIN
+#include "debug.h"
+#include "hash.h"
+#include "pkcs11.h"
+#include "p11-kit.h"
+#include "pin.h"
+#include "private.h"
+#include "ptr-array.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * SECTION:p11-pin
+ * @title: PIN Callbacks
+ * @short_description: PIN Callbacks
+ *
+ * Applications can register a callback which will be called to provide a password
+ * associated with a given pin file.
+ * PKCS\#11 URIs can be used in configuration files or applications to represent
+ * PKCS\#11 modules, tokens or objects. An example of a URI might be:
+ *
+ * <code><literallayout>
+ * pkcs11:token=The\%20Software\%20PKCS\#11\%20softtoken;
+ * manufacturer=Snake\%20Oil,\%20Inc.;serial=;object=my-certificate;
+ * model=1.0;objecttype=cert;id=\%69\%95\%3e\%5c\%f4\%bd\%ec\%91
+ * </literallayout></code>
+ *
+ * You can use p11_kit_uri_parse() to parse such a URI, and p11_kit_uri_format()
+ * to build one. URIs are represented by the #P11KitUri structure. You can match
+ * a parsed URI against PKCS\#11 tokens with p11_kit_uri_match_token_info()
+ * or attributes with p11_kit_uri_match_attributes().
+ *
+ * Since URIs can represent different sorts of things, when parsing or formatting
+ * a URI a 'context' can be used to indicate which sort of URI is expected.
+ *
+ * URIs have an <code>unrecognized</code> flag. This flag is set during parsing
+ * if any parts of the URI are not recognized. This may be because the part is
+ * from a newer version of the PKCS\#11 spec or because that part was not valid
+ * inside of the desired context used when parsing.
+ */
+
+/**
+ * P11KitUri:
+ *
+ * A structure representing a PKCS\#11 URI. There are no public fields
+ * visible in this structure. Use the various accessor functions.
+ */
+
+/**
+ * P11KitUriType:
+ * @P11_KIT_URI_FOR_OBJECT: The URI represents one or more objects
+ * @P11_KIT_URI_FOR_TOKEN: The URI represents one or more tokens
+ * @P11_KIT_URI_FOR_MODULE: The URI represents one or more modules
+ * @P11_KIT_URI_FOR_MODULE_WITH_VERSION: The URI represents a module with
+ * a specific version.
+ * @P11_KIT_URI_FOR_OBJECT_ON_TOKEN: The URI represents one or more objects
+ * that are present on a specific token.
+ * @P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE: The URI represents one or more
+ * objects that are present on a specific token, being used with a certain
+ * module.
+ * @P11_KIT_URI_FOR_ANY: The URI can represent anything
+ *
+ * A PKCS\#11 URI can represent different kinds of things. This flag is used by
+ * p11_kit_uri_parse() to denote in what context the URI will be used.
+ *
+ * The various types can be combined.
+ */
+
+/**
+ * P11KitUriResult:
+ * @P11_KIT_URI_OK: Success
+ * @P11_KIT_URI_NO_MEMORY: Memory allocation failed
+ * @P11_KIT_URI_BAD_SCHEME: The URI had a bad scheme
+ * @P11_KIT_URI_BAD_ENCODING: The URI had a bad encoding
+ * @P11_KIT_URI_BAD_SYNTAX: The URI had a bad syntax
+ * @P11_KIT_URI_BAD_VERSION: The URI contained a bad version number
+ * @P11_KIT_URI_NOT_FOUND: A requested part of the URI was not found
+ *
+ * Error codes returned by various functions. The functions each clearly state
+ * which error codes they are capable of returning.
+ */
+
+/**
+ * P11_KIT_URI_SCHEME:
+ *
+ * String of URI scheme for PKCS\#11 URIs.
+ */
+
+/**
+ * P11_KIT_URI_SCHEME_LEN:
+ *
+ * Length of %P11_KIT_URI_SCHEME.
+ */
+
+typedef struct _PinfileCallback {
+ /* Only used/modified within the lock */
+ int refs;
+
+ /* Readonly after construct */
+ p11_kit_pin_callback func;
+ void *user_data;
+ p11_kit_pin_callback_destroy destroy;
+} PinfileCallback;
+
+/*
+ * Shared data between threads, protected by the mutex, a structure so
+ * we can audit thread safety easier.
+ */
+static struct _Shared {
+ hash_t *pinfiles;
+} gl = { NULL };
+
+static void*
+ref_pinfile_callback (void *pointer)
+{
+ PinfileCallback *cb = pointer;
+ cb->refs++;
+ return pointer;
+}
+
+static void
+unref_pinfile_callback (void *pointer)
+{
+ PinfileCallback *cb = pointer;
+ assert (cb->refs >= 1);
+
+ cb->refs--;
+ if (cb->refs == 0) {
+ if (cb->destroy)
+ (cb->destroy) (cb->user_data);
+ free (cb);
+ }
+}
+
+int
+p11_kit_pin_register_callback (const char *pinfile, p11_kit_pin_callback callback,
+ void *callback_data, p11_kit_pin_callback_destroy callback_destroy)
+{
+ PinfileCallback *cb;
+ ptr_array_t *callbacks;
+ char *name;
+ int ret;
+
+ cb = calloc (1, sizeof (PinfileCallback));
+ if (cb == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ name = strdup (pinfile);
+ if (name == NULL) {
+ free (cb);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ cb->refs = 1;
+ cb->func = callback;
+ cb->user_data = callback_data;
+ cb->destroy = callback_destroy;
+
+ _p11_lock ();
+
+ if (gl.pinfiles == NULL) {
+ gl.pinfiles = hash_create (hash_string_hash, hash_string_equal,
+ free, (hash_destroy_func)ptr_array_free);
+ if (gl.pinfiles == NULL) {
+ errno = ENOMEM;
+ ret = -1;
+ }
+ }
+
+ if (gl.pinfiles != NULL)
+ callbacks = hash_get (gl.pinfiles, pinfile);
+
+ if (callbacks == NULL) {
+ callbacks = ptr_array_create (unref_pinfile_callback);
+ if (callbacks == NULL) {
+ errno = ENOMEM;
+ ret = -1;
+ } else if (!hash_set (gl.pinfiles, name, callbacks)) {
+ ptr_array_free (callbacks);
+ callbacks = NULL;
+ errno = ENOMEM;
+ ret = -1;
+ } else {
+ /* Note that we've consumed the name */
+ name = NULL;
+ }
+ }
+
+ if (callbacks != NULL) {
+ if (ptr_array_add (callbacks, cb) < 0) {
+ errno = ENOMEM;
+ ret = -1;
+ } else {
+ /* Note that we've consumed the callback */
+ cb = NULL;
+ }
+ }
+
+ _p11_unlock ();
+
+ /* Unless consumed above */
+ free (name);
+ if (cb != NULL)
+ unref_pinfile_callback (cb);
+
+ return ret;
+}
+
+void
+p11_kit_pin_unregister_callback (const char *pinfile, p11_kit_pin_callback callback,
+ void *callback_data)
+{
+ PinfileCallback *cb;
+ ptr_array_t *callbacks;
+ unsigned int i;
+
+ _p11_lock ();
+
+ if (gl.pinfiles) {
+ callbacks = hash_get (gl.pinfiles, pinfile);
+ if (callbacks) {
+ for (i = 0; i < ptr_array_count (callbacks); i++) {
+ cb = ptr_array_at (callbacks, i);
+ if (cb->func == callback && cb->user_data == callback_data) {
+ ptr_array_remove (callbacks, i);
+ break;
+ }
+ }
+
+ if (ptr_array_count (callbacks) == 0)
+ hash_remove (gl.pinfiles, pinfile);
+ }
+
+ /* When there are no more pinfiles, get rid of the hash table */
+ if (hash_count (gl.pinfiles) == 0) {
+ hash_free (gl.pinfiles);
+ gl.pinfiles = NULL;
+ }
+ }
+
+ _p11_unlock ();
+}
+
+int
+p11_kit_pin_read_pinfile (const char *pinfile, P11KitUri *pin_uri,
+ const char *pin_description, P11KitPinFlags flags,
+ char *pin, size_t pin_max)
+{
+ PinfileCallback **snapshot = NULL;
+ unsigned int snapshot_count = 0;
+ ptr_array_t *callbacks;
+ unsigned int i;
+ int ret;
+
+ _p11_lock ();
+
+ /* Find and ref the pinfile data */
+ if (gl.pinfiles) {
+ callbacks = hash_get (gl.pinfiles, pinfile);
+
+ /* If we didn't find any snapshots try the global ones */
+ if (callbacks == NULL)
+ callbacks = hash_get (gl.pinfiles, P11_KIT_PIN_FALLBACK);
+
+ if (callbacks != NULL) {
+ snapshot = (PinfileCallback**)ptr_array_snapshot (callbacks);
+ snapshot_count = ptr_array_count (callbacks);
+ for (i = 0; i < snapshot_count; i++)
+ ref_pinfile_callback (snapshot[i]);
+ }
+ }
+
+ _p11_unlock ();
+
+ if (snapshot == NULL)
+ return 0;
+
+ for (i = 0; i < snapshot_count; i++) {
+ ret = (snapshot[i]->func) (pinfile, pin_uri, pin_description, flags,
+ snapshot[i]->user_data, pin, pin_max);
+ }
+
+ _p11_lock ();
+ for (i = 0; i < snapshot_count; i++)
+ unref_pinfile_callback (snapshot[i]);
+ free (snapshot);
+ _p11_unlock ();
+
+ return ret;
+}
diff --git a/p11-kit/pin.h b/p11-kit/pin.h
new file mode 100644
index 0000000..780e72d
--- /dev/null
+++ b/p11-kit/pin.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2011 Collabora Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@collabora.co.uk>
+ */
+
+#ifndef P11_KIT_PIN_H
+#define P11_KIT_PIN_H
+
+#include <p11-kit/uri.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ P11_KIT_PIN_FLAGS_USER_LOGIN = 1,
+ P11_KIT_PIN_FLAGS_SO_LOGIN = 2,
+ P11_KIT_PIN_FLAGS_CONTEXT_LOGIN = 4,
+ P11_KIT_PIN_FLAGS_RETRY = 10,
+ P11_KIT_PIN_FLAGS_MANY_TRIES = 20,
+ P11_KIT_PIN_FLAGS_FINAL_TRY = 40
+} P11KitPinFlags;
+
+#define P11_KIT_PIN_FALLBACK ""
+
+typedef int (*p11_kit_pin_callback) (const char *pinfile,
+ P11KitUri *pin_uri,
+ const char *pin_description,
+ P11KitPinFlags pin_flags,
+ void *callback_data,
+ char *pin,
+ size_t pin_max);
+
+typedef void (*p11_kit_pin_callback_destroy) (void *callback_data);
+
+int p11_kit_pin_register_callback (const char *pinfile,
+ p11_kit_pin_callback callback,
+ void *callback_data,
+ p11_kit_pin_callback_destroy callback_destroy);
+
+void p11_kit_pin_unregister_callback (const char *pinfile,
+ p11_kit_pin_callback callback,
+ void *callback_data);
+
+int p11_kit_pin_read_pinfile (const char *pinfile,
+ P11KitUri *pin_uri,
+ const char *pin_description,
+ P11KitPinFlags pin_flags,
+ char *pin,
+ size_t pin_max);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* P11_KIT_URI_H */
diff --git a/p11-kit/ptr-array.c b/p11-kit/ptr-array.c
new file mode 100644
index 0000000..6a5ac4f
--- /dev/null
+++ b/p11-kit/ptr-array.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2011 Collabora Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include "config.h"
+
+#include "ptr-array.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+struct ptr_array {
+ void **memory;
+ unsigned int length;
+ unsigned int allocated;
+ ptr_array_destroy_func destroy;
+};
+
+static int
+maybe_expand_array (ptr_array_t *array, unsigned int length)
+{
+ unsigned int new_allocated;
+ void **new_memory;
+
+ if (length <= array->allocated)
+ return 1;
+
+ new_allocated = array->allocated + 16;
+ if (new_allocated < length)
+ new_allocated = length;
+
+ new_memory = realloc (array->memory, new_allocated * sizeof (void*));
+ if (new_memory == NULL)
+ return 0;
+
+ array->memory = new_memory;
+ array->allocated = new_allocated;
+ return 1;
+}
+
+ptr_array_t*
+ptr_array_create (ptr_array_destroy_func destroy_func)
+{
+ ptr_array_t *array;
+
+ array = calloc (1, sizeof (ptr_array_t));
+ if (array == NULL)
+ return NULL;
+
+ if (!maybe_expand_array (array, 2)) {
+ ptr_array_free (array);
+ return NULL;
+ }
+
+ array->destroy = destroy_func;
+ return array;
+}
+
+void
+ptr_array_free (ptr_array_t *array)
+{
+ unsigned int i;
+
+ if (array == NULL)
+ return;
+
+ if (array->destroy) {
+ for (i = 0; i < array->length; i++)
+ (array->destroy) (array->memory[i]);
+ }
+
+ free (array->memory);
+ free (array);
+}
+
+unsigned int
+ptr_array_count (ptr_array_t *array)
+{
+ return array->length;
+}
+
+int
+ptr_array_add (ptr_array_t *array, void *value)
+{
+ if (!maybe_expand_array (array, array->length + 1))
+ return 0;
+
+ array->memory[array->length] = value;
+ array->length++;
+ return 1;
+}
+
+void
+ptr_array_remove (ptr_array_t *array, unsigned int index)
+{
+ if (array->destroy)
+ (array->destroy) (array->memory[index]);
+ memmove (array->memory + index, array->memory + index + 1,
+ (array->length - (index + 1)) * sizeof (void*));
+ array->length--;
+}
+
+void*
+ptr_array_at (ptr_array_t *array, unsigned int index)
+{
+ return array->memory[index];
+}
+
+void**
+ptr_array_snapshot (ptr_array_t *array)
+{
+ void **snapshot;
+ size_t bytes;
+
+ bytes = array->length * sizeof (void*);
+ snapshot = malloc (bytes);
+ if (!snapshot)
+ return NULL;
+
+ memcpy (snapshot, array->memory, bytes);
+ return snapshot;
+}
diff --git a/p11-kit/ptr-array.h b/p11-kit/ptr-array.h
new file mode 100644
index 0000000..acd894d
--- /dev/null
+++ b/p11-kit/ptr-array.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011 Collabora Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Waler <stefw@collabora.co.uk>
+ */
+
+#ifndef __PTR_ARRAY_H__
+#define __PTR_ARRAY_H__
+
+#include <sys/types.h>
+
+typedef struct ptr_array ptr_array_t;
+
+typedef void (*ptr_array_destroy_func) (void *data);
+
+ptr_array_t* ptr_array_create (ptr_array_destroy_func destroy_func);
+
+void ptr_array_free (ptr_array_t *array);
+
+unsigned int ptr_array_count (ptr_array_t *array);
+
+int ptr_array_add (ptr_array_t *array,
+ void *value);
+
+void ptr_array_remove (ptr_array_t *array,
+ unsigned int index);
+
+void* ptr_array_at (ptr_array_t *array,
+ unsigned int index);
+
+void** ptr_array_snapshot (ptr_array_t *array);
+
+#endif /* __PTR_ARRAY_H__ */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 6b988b8..cde804f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -8,22 +8,32 @@ INCLUDES = \
noinst_PROGRAMS = \
hash-test \
+ ptr-array-test \
conf-test \
- uri-test
+ uri-test \
+ pin-test
hash_test_LDADD = \
$(top_builddir)/p11-kit/libp11-kit-testable.la
+ptr_array_test_LDADD = \
+ $(top_builddir)/p11-kit/libp11-kit-testable.la
+
conf_test_LDADD = \
$(top_builddir)/p11-kit/libp11-kit-testable.la
uri_test_LDADD = \
$(top_builddir)/p11-kit/libp11-kit-testable.la
+pin_test_LDADD = \
+ $(top_builddir)/p11-kit/libp11-kit-testable.la
+
check-am:
./hash-test
+ ./ptr-array-test
./conf-test
./uri-test
+ ./pin-test
EXTRA_DIST = \
cutest \
diff --git a/tests/pin-test.c b/tests/pin-test.c
new file mode 100644
index 0000000..7f1bc08
--- /dev/null
+++ b/tests/pin-test.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2011, Collabora Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@collabora.co.uk>
+ */
+
+#include "config.h"
+#include "CuTest.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "p11-kit/pin.h"
+
+static int
+callback_one (const char *pinfile, P11KitUri *pin_uri, const char *pin_description,
+ P11KitPinFlags pin_flags, void *callback_data, char *pin,
+ size_t pin_max)
+{
+ int *data = callback_data;
+ assert (*data == 33);
+ strncpy (pin, "one", pin_max);
+ return 1;
+}
+
+static int
+callback_other (const char *pinfile, P11KitUri *pin_uri, const char *pin_description,
+ P11KitPinFlags pin_flags, void *callback_data, char *pin,
+ size_t pin_max)
+{
+ char *data = callback_data;
+ strncpy (pin, data, pin_max);
+ return 1;
+}
+
+static void
+destroy_data (void *callback_data)
+{
+ int *data = callback_data;
+ (*data)++;
+}
+
+static void
+test_pin_register_unregister (CuTest *tc)
+{
+ int data = 33;
+
+ p11_kit_pin_register_callback ("/the/pinfile", callback_one,
+ &data, destroy_data);
+
+ p11_kit_pin_unregister_callback ("/the/pinfile", callback_one,
+ &data);
+
+ CuAssertIntEquals (tc, 34, data);
+}
+
+static void
+test_pin_read (CuTest *tc)
+{
+ P11KitUri *uri;
+ char buffer[256];
+ int data = 33;
+ int ret;
+
+ p11_kit_pin_register_callback ("/the/pinfile", callback_one,
+ &data, destroy_data);
+
+ uri = p11_kit_uri_new ();
+ ret = p11_kit_pin_read_pinfile ("/the/pinfile", uri, "The token",
+ P11_KIT_PIN_FLAGS_USER_LOGIN,
+ buffer, sizeof (buffer));
+ p11_kit_uri_free (uri);
+
+ CuAssertIntEquals (tc, 1, ret);
+ CuAssertStrEquals (tc, "one", buffer);
+
+ p11_kit_pin_unregister_callback ("/the/pinfile", callback_one,
+ &data);
+}
+
+static void
+test_pin_read_no_match (CuTest *tc)
+{
+ P11KitUri *uri;
+ char buffer[256];
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ ret = p11_kit_pin_read_pinfile ("/the/pinfile", uri, "The token",
+ P11_KIT_PIN_FLAGS_USER_LOGIN,
+ buffer, sizeof (buffer));
+ p11_kit_uri_free (uri);
+
+ CuAssertIntEquals (tc, 0, ret);
+}
+
+static void
+test_pin_register_duplicate (CuTest *tc)
+{
+ P11KitUri *uri;
+ char *value = "secret";
+ char buffer[256];
+ int data = 33;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+
+ p11_kit_pin_register_callback ("/the/pinfile", callback_one,
+ &data, destroy_data);
+
+ p11_kit_pin_register_callback ("/the/pinfile", callback_other,
+ value, NULL);
+
+ ret = p11_kit_pin_read_pinfile ("/the/pinfile", uri, "The token",
+ P11_KIT_PIN_FLAGS_USER_LOGIN,
+ buffer, sizeof (buffer));
+
+ CuAssertIntEquals (tc, 1, ret);
+ CuAssertStrEquals (tc, "secret", buffer);
+
+ p11_kit_pin_unregister_callback ("/the/pinfile", callback_other,
+ value);
+
+ ret = p11_kit_pin_read_pinfile ("/the/pinfile", uri, "The token",
+ P11_KIT_PIN_FLAGS_USER_LOGIN,
+ buffer, sizeof (buffer));
+
+ CuAssertIntEquals (tc, 1, ret);
+ CuAssertStrEquals (tc, "one", buffer);
+
+ p11_kit_pin_unregister_callback ("/the/pinfile", callback_one,
+ &data);
+
+ ret = p11_kit_pin_read_pinfile ("/the/pinfile", uri, "The token",
+ P11_KIT_PIN_FLAGS_USER_LOGIN,
+ buffer, sizeof (buffer));
+
+ CuAssertIntEquals (tc, 0, ret);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_pin_register_fallback (CuTest *tc)
+{
+ char *value = "secret";
+ P11KitUri *uri;
+ char buffer[256];
+ int data = 33;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+
+ p11_kit_pin_register_callback (P11_KIT_PIN_FALLBACK, callback_one,
+ &data, destroy_data);
+
+ ret = p11_kit_pin_read_pinfile ("/the/pinfile", uri, "The token",
+ P11_KIT_PIN_FLAGS_USER_LOGIN,
+ buffer, sizeof (buffer));
+
+ CuAssertIntEquals (tc, 1, ret);
+ CuAssertStrEquals (tc, "one", buffer);
+
+ p11_kit_pin_register_callback ("/the/pinfile", callback_other,
+ value, NULL);
+
+ ret = p11_kit_pin_read_pinfile ("/the/pinfile", uri, "The token",
+ P11_KIT_PIN_FLAGS_USER_LOGIN,
+ buffer, sizeof (buffer));
+
+ CuAssertIntEquals (tc, 1, ret);
+ CuAssertStrEquals (tc, "secret", buffer);
+
+ p11_kit_pin_unregister_callback ("/the/pinfile", callback_other,
+ value);
+
+ p11_kit_pin_unregister_callback (P11_KIT_PIN_FALLBACK, callback_one,
+ &data);
+
+ p11_kit_uri_free (uri);
+}
+
+int
+main (void)
+{
+ CuString *output = CuStringNew ();
+ CuSuite* suite = CuSuiteNew ();
+ int ret;
+
+ SUITE_ADD_TEST (suite, test_pin_register_unregister);
+ SUITE_ADD_TEST (suite, test_pin_read);
+ SUITE_ADD_TEST (suite, test_pin_read_no_match);
+ SUITE_ADD_TEST (suite, test_pin_register_duplicate);
+ SUITE_ADD_TEST (suite, test_pin_register_fallback);
+
+ CuSuiteRun (suite);
+ CuSuiteSummary (suite, output);
+ CuSuiteDetails (suite, output);
+ printf ("%s\n", output->buffer);
+ ret = suite->failCount;
+ CuSuiteDelete (suite);
+ CuStringDelete (output);
+
+ return ret;
+}
+
+#include "CuTest.c"
diff --git a/tests/ptr-array-test.c b/tests/ptr-array-test.c
new file mode 100644
index 0000000..ff9959d
--- /dev/null
+++ b/tests/ptr-array-test.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2011, Collabora Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@collabora.co.uk>
+ */
+
+#include "config.h"
+#include "CuTest.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ptr-array.h"
+
+static void
+test_ptr_array_create (CuTest *tc)
+{
+ ptr_array_t *array;
+
+ array = ptr_array_create (NULL);
+ CuAssertPtrNotNull (tc, array);
+ ptr_array_free (array);
+}
+
+static void
+test_ptr_array_free_null (CuTest *tc)
+{
+ ptr_array_free (NULL);
+}
+
+static void
+destroy_value (void *data)
+{
+ int *value = data;
+ *value = 2;
+}
+
+static void
+test_ptr_array_free_destroys (CuTest *tc)
+{
+ ptr_array_t *array;
+ int value = 0;
+
+ array = ptr_array_create (destroy_value);
+ CuAssertPtrNotNull (tc, array);
+ if (!ptr_array_add (array, &value))
+ CuFail (tc, "should not be reached");
+ ptr_array_free (array);
+
+ CuAssertIntEquals (tc, 2, value);
+}
+
+#if 0
+static void
+test_hash_iterate (CuTest *tc)
+{
+ hash_t *ht;
+ hash_iter_t hi;
+ int key = 1;
+ int value = 2;
+ void *pkey;
+ void *pvalue;
+ int ret;
+
+ ht = hash_create (hash_direct_hash, hash_direct_equal, NULL, NULL);
+ CuAssertPtrNotNull (tc, ht);
+ if (!hash_set (ht, &key, &value))
+ CuFail (tc, "should not be reached");
+
+ hash_iterate (ht, &hi);
+
+ ret = hash_next (&hi, &pkey, &pvalue);
+ CuAssertIntEquals (tc, 1, ret);
+ CuAssertPtrEquals (tc, pkey, &key);
+ CuAssertPtrEquals (tc, pvalue, &value);
+
+ ret = hash_next (&hi, &pkey, &pvalue);
+ CuAssertIntEquals (tc, 0, ret);
+
+ hash_free (ht);
+}
+
+#endif
+
+static void
+test_ptr_array_add (CuTest *tc)
+{
+ char *value = "VALUE";
+ char *check;
+ ptr_array_t *array;
+
+ array = ptr_array_create (NULL);
+ if (!ptr_array_add (array, value))
+ CuFail (tc, "should not be reached");
+
+ CuAssertIntEquals (tc, 1, ptr_array_count (array));
+
+ check = ptr_array_at (array, 0);
+ CuAssertPtrEquals (tc, check, value);
+
+ ptr_array_free (array);
+}
+
+static void
+test_ptr_array_add_remove (CuTest *tc)
+{
+ char *value = "VALUE";
+ char *check;
+ ptr_array_t *array;
+
+ array = ptr_array_create (NULL);
+ if (!ptr_array_add (array, value))
+ CuFail (tc, "should not be reached");
+
+ CuAssertIntEquals (tc, 1, ptr_array_count (array));
+
+ check = ptr_array_at (array, 0);
+ CuAssertPtrEquals (tc, check, value);
+
+ ptr_array_remove (array, 0);
+
+ CuAssertIntEquals (tc, 0, ptr_array_count (array));
+
+ ptr_array_free (array);
+}
+
+static void
+test_ptr_array_remove_destroys (CuTest *tc)
+{
+ ptr_array_t *array;
+ int value = 0;
+
+ array = ptr_array_create (destroy_value);
+ if (!ptr_array_add (array, &value))
+ CuFail (tc, "should not be reached");
+
+ ptr_array_remove (array, 0);
+
+ CuAssertIntEquals (tc, 2, value);
+
+ /* should not be destroyed again */
+ value = 0;
+
+ ptr_array_free (array);
+
+ CuAssertIntEquals (tc, 0, value);
+}
+
+static void
+test_ptr_array_remove_and_count (CuTest *tc)
+{
+ ptr_array_t *array;
+ int *value;
+ int i;
+
+ array = ptr_array_create (free);
+
+ CuAssertIntEquals (tc, 0, ptr_array_count (array));
+
+ for (i = 0; i < 20000; ++i) {
+ value = malloc (sizeof (int));
+ *value = i;
+ if (!ptr_array_add (array, value))
+ CuFail (tc, "should not be reached");
+ CuAssertIntEquals (tc, i + 1, ptr_array_count (array));
+ }
+
+ for (i = 10; i < 20000; ++i) {
+ ptr_array_remove (array, 10);
+ CuAssertIntEquals (tc, 20010 - (i + 1), ptr_array_count (array));
+ }
+
+ CuAssertIntEquals (tc, 10, ptr_array_count (array));
+
+ ptr_array_free (array);
+}
+
+static void
+test_ptr_array_snapshot (CuTest *tc)
+{
+ ptr_array_t *array;
+ void **snapshot;
+
+ array = ptr_array_create (NULL);
+
+ ptr_array_add (array, "1");
+ ptr_array_add (array, "2");
+ ptr_array_add (array, "3");
+ ptr_array_add (array, "4");
+ CuAssertIntEquals (tc, 4, ptr_array_count (array));
+
+ snapshot = ptr_array_snapshot (array);
+
+ CuAssertStrEquals (tc, "1", snapshot[0]);
+ CuAssertStrEquals (tc, "2", snapshot[1]);
+ CuAssertStrEquals (tc, "3", snapshot[2]);
+ CuAssertStrEquals (tc, "4", snapshot[3]);
+
+ free (snapshot);
+ ptr_array_free (array);
+}
+
+int
+main (void)
+{
+ CuString *output = CuStringNew ();
+ CuSuite* suite = CuSuiteNew ();
+ int ret;
+
+ SUITE_ADD_TEST (suite, test_ptr_array_create);
+ SUITE_ADD_TEST (suite, test_ptr_array_add);
+ SUITE_ADD_TEST (suite, test_ptr_array_add_remove);
+ SUITE_ADD_TEST (suite, test_ptr_array_remove_destroys);
+ SUITE_ADD_TEST (suite, test_ptr_array_remove_and_count);
+ SUITE_ADD_TEST (suite, test_ptr_array_free_null);
+ SUITE_ADD_TEST (suite, test_ptr_array_free_destroys);
+ SUITE_ADD_TEST (suite, test_ptr_array_snapshot);
+
+ CuSuiteRun (suite);
+ CuSuiteSummary (suite, output);
+ CuSuiteDetails (suite, output);
+ printf ("%s\n", output->buffer);
+ ret = suite->failCount;
+ CuSuiteDelete (suite);
+ CuStringDelete (output);
+
+ return ret;
+}
+
+#include "CuTest.c"