summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stefw@collabora.co.uk>2011-02-19 16:33:36 +0100
committerStef Walter <stefw@collabora.co.uk>2011-02-19 16:33:36 +0100
commit1d9ca2ddb4df85b7235ec78e4996cf2d1fd775a2 (patch)
tree027f6df6ca2207daa687f8775a4442e68d065965
parent65509aa3a7c35d8bd5a947ca87c14d4de11deb21 (diff)
Reference implementation of PKCS#11 URIs
-rw-r--r--.gitignore1
-rw-r--r--module/Makefile.am3
-rw-r--r--module/p11-kit-proxy.c14
-rw-r--r--module/p11-kit-uri.c886
-rw-r--r--module/p11-kit-uri.h101
-rw-r--r--module/p11-kit.h2
-rw-r--r--module/util.c51
-rw-r--r--module/util.h45
-rw-r--r--tests/Makefile.am7
-rw-r--r--tests/uri-test.c1050
10 files changed, 2146 insertions, 14 deletions
diff --git a/.gitignore b/.gitignore
index 6788a07..601cff0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,3 +45,4 @@ temp.txt
/tests/coverage.info
/tests/hash-test
/tests/conf-test
+/tests/uri-test
diff --git a/module/Makefile.am b/module/Makefile.am
index 49f0a3d..b4339a8 100644
--- a/module/Makefile.am
+++ b/module/Makefile.am
@@ -4,15 +4,18 @@ incdir = $(includedir)/p11-kit
inc_HEADERS = \
p11-kit.h \
+ p11-kit-uri.h \
pkcs11.h
MODULE_SRCS = \
conf.c conf.h \
hash.c hash.h \
+ util.c util.h \
p11-kit-lib.c \
p11-kit-proxy.c \
p11-kit-private.h \
p11-kit-messages.c \
+ p11-kit-uri.c \
$(inc_HEADERS)
lib_LTLIBRARIES = \
diff --git a/module/p11-kit-proxy.c b/module/p11-kit-proxy.c
index 02f8ac3..3b43a5f 100644
--- a/module/p11-kit-proxy.c
+++ b/module/p11-kit-proxy.c
@@ -39,6 +39,7 @@
#include "pkcs11.h"
#include "p11-kit.h"
#include "p11-kit-private.h"
+#include "util.h"
#include <sys/types.h>
#include <assert.h>
@@ -87,19 +88,6 @@ static struct _Shared {
#define LIBRARY_VERSION_MINOR 1
/* -----------------------------------------------------------------------------
- * UTILITIES
- */
-
-static void*
-xrealloc (void * memory, size_t length)
-{
- void *allocated = realloc (memory, length);
- if (!allocated)
- free (memory);
- return allocated;
-}
-
-/* -----------------------------------------------------------------------------
* PKCS#11 PROXY MODULE
*/
diff --git a/module/p11-kit-uri.c b/module/p11-kit-uri.c
new file mode 100644
index 0000000..8c65301
--- /dev/null
+++ b/module/p11-kit-uri.c
@@ -0,0 +1,886 @@
+/*
+ * 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 "pkcs11.h"
+#include "p11-kit-uri.h"
+#include "util.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+enum {
+ CLASS_IDX,
+ LABEL_IDX,
+ ID_IDX,
+ NUM_ATTRS,
+};
+
+struct _P11KitUri {
+ int unrecognized;
+ CK_INFO module;
+ CK_TOKEN_INFO token;
+ CK_ATTRIBUTE attrs[NUM_ATTRS];
+};
+
+const static char HEX_CHARS[] = "0123456789abcdef";
+
+static int
+url_decode (const char *value, const char *end,
+ unsigned char** output, size_t *length)
+{
+ char *a, *b;
+ unsigned char *result, *p;
+
+ assert (output);
+ assert (value <= end);
+
+ /* String can only get shorter */
+ result = malloc ((end - value) + 1);
+ if (!result)
+ return P11_KIT_URI_NO_MEMORY;
+
+ /* Now loop through looking for escapes */
+ p = result;
+ while (value != end) {
+ /*
+ * A percent sign followed by two hex digits means
+ * that the digits represent an escaped character.
+ */
+ if (*value == '%') {
+ value++;
+ if (value + 2 > end) {
+ free (result);
+ return P11_KIT_URI_BAD_ENCODING;
+ }
+ a = strchr (HEX_CHARS, tolower (value[0]));
+ b = strchr (HEX_CHARS, tolower (value[1]));
+ if (!a || !b) {
+ free (result);
+ return P11_KIT_URI_BAD_ENCODING;
+ }
+ *p = (a - HEX_CHARS) << 4;
+ *(p++) |= (b - HEX_CHARS);
+ value += 2;
+ } else {
+ *(p++) = *(value++);
+ }
+ }
+
+ *p = 0;
+ if (length)
+ *length = p - result;
+ *output = result;
+ return P11_KIT_URI_OK;
+}
+
+static char*
+url_encode (const unsigned char *value, const unsigned char *end, size_t *length)
+{
+ char *p;
+ char *result;
+
+ assert (value <= end);
+
+ /* Just allocate for worst case */
+ result = malloc (((end - value) * 3) + 1);
+ if (!result)
+ return NULL;
+
+ /* Now loop through looking for escapes */
+ p = result;
+ while (value != end) {
+
+ /* These characters we let through verbatim */
+ if (isalnum (*value) || strchr ("_-.", *value) != NULL) {
+ *(p++) = *(value++);
+
+ /* All others get encoded */
+ } else {
+ *(p++) = '%';
+ *(p++) = HEX_CHARS[((unsigned char)*value) >> 4];
+ *(p++) = HEX_CHARS[((unsigned char)*value) & 0x0F];
+ ++value;
+ }
+ }
+
+ *p = 0;
+ if (length)
+ *length = p - result;
+ return result;
+}
+
+static int
+attribute_to_idx (CK_ATTRIBUTE_TYPE type)
+{
+ switch (type) {
+ case CKA_CLASS:
+ return CLASS_IDX;
+ case CKA_LABEL:
+ return LABEL_IDX;
+ case CKA_ID:
+ return ID_IDX;
+ default:
+ return -1;
+ }
+}
+
+static CK_ATTRIBUTE_TYPE
+idx_to_attribute (int idx)
+{
+ switch (idx) {
+ case CLASS_IDX:
+ return CKA_CLASS;
+ case LABEL_IDX:
+ return CKA_LABEL;
+ case ID_IDX:
+ return CKA_ID;
+ default:
+ assert (0);
+ }
+}
+
+static int
+match_struct_string (const unsigned char *inuri, const unsigned char *real,
+ size_t length)
+{
+ assert (inuri);
+ assert (real);
+ assert (length > 0);
+
+ /* NULL matches anything */
+ if (inuri[0] == 0)
+ return 1;
+
+ return memcmp (inuri, real, length) == 0 ? 1 : 0;
+}
+
+static int
+match_struct_version (CK_VERSION_PTR inuri, CK_VERSION_PTR real)
+{
+ /* This matches anything */
+ if (inuri->major == (CK_BYTE)-1 && inuri->minor == (CK_BYTE)-1)
+ return 1;
+
+ return memcmp (inuri, real, sizeof (CK_VERSION));
+}
+
+CK_INFO_PTR
+p11_kit_uri_get_module_info (P11KitUri *uri)
+{
+ assert (uri);
+ return &uri->module;
+}
+
+int
+p11_kit_uri_match_module_info (P11KitUri *uri, CK_INFO_PTR info)
+{
+ assert (uri);
+ assert (info);
+
+ if (uri->unrecognized)
+ return 0;
+
+ return (match_struct_string (uri->module.libraryDescription,
+ info->libraryDescription,
+ sizeof (info->libraryDescription)) &&
+ match_struct_string (uri->module.manufacturerID,
+ info->manufacturerID,
+ sizeof (info->manufacturerID)) &&
+ match_struct_version (&uri->module.libraryVersion,
+ &info->libraryVersion));
+}
+
+CK_TOKEN_INFO_PTR
+p11_kit_uri_get_token_info (P11KitUri *uri)
+{
+ assert (uri);
+ return &uri->token;
+}
+
+int
+p11_kit_uri_match_token_info (P11KitUri *uri, CK_TOKEN_INFO_PTR token_info)
+{
+ assert (uri);
+ assert (token_info);
+
+ if (uri->unrecognized)
+ return 0;
+
+ return (match_struct_string (uri->token.label,
+ token_info->label,
+ sizeof (token_info->label)) &&
+ match_struct_string (uri->token.manufacturerID,
+ token_info->manufacturerID,
+ sizeof (token_info->manufacturerID)) &&
+ match_struct_string (uri->token.model,
+ token_info->model,
+ sizeof (token_info->model)) &&
+ match_struct_string (uri->token.serialNumber,
+ token_info->serialNumber,
+ sizeof (token_info->serialNumber)));
+}
+
+CK_ATTRIBUTE_PTR
+p11_kit_uri_get_attribute (P11KitUri *uri, CK_ATTRIBUTE_TYPE type)
+{
+ int idx;
+
+ assert (uri);
+
+ idx = attribute_to_idx (type);
+ if (idx < 0)
+ return NULL;
+
+ assert (idx < NUM_ATTRS);
+ if (uri->attrs[idx].ulValueLen == (CK_ULONG)-1)
+ return NULL;
+ return &uri->attrs[idx];
+}
+
+int
+p11_kit_uri_set_attribute (P11KitUri *uri, CK_ATTRIBUTE_PTR attr)
+{
+ void *value = NULL;
+ int idx;
+ int ret;
+
+ assert (uri);
+ assert (attr);
+
+ if (attr->pValue && attr->ulValueLen && attr->ulValueLen != (CK_ULONG)-1) {
+ value = malloc (attr->ulValueLen);
+ if (!value)
+ return P11_KIT_URI_NO_MEMORY;
+ memcpy (value, attr->pValue, attr->ulValueLen);
+ }
+
+ ret = p11_kit_uri_clear_attribute (uri, attr->type);
+ if (ret < 0){
+ free (value);
+ return ret;
+ }
+
+ idx = attribute_to_idx (attr->type);
+ assert (idx >= 0 && idx < NUM_ATTRS);
+
+ memcpy (&uri->attrs[idx], attr, sizeof (CK_ATTRIBUTE));
+ uri->attrs[idx].pValue = value;
+
+ return P11_KIT_URI_OK;
+}
+
+int
+p11_kit_uri_clear_attribute (P11KitUri *uri, CK_ATTRIBUTE_TYPE type)
+{
+ int idx;
+
+ assert (uri);
+
+ idx = attribute_to_idx (type);
+ if (idx < 0)
+ return P11_KIT_URI_NOT_FOUND;
+ assert (idx < NUM_ATTRS);
+
+ free (uri->attrs[idx].pValue);
+ uri->attrs[idx].pValue = NULL;
+ uri->attrs[idx].ulValueLen = (CK_ULONG)-1;
+ return 0;
+}
+
+static int
+match_attributes (CK_ATTRIBUTE_PTR one, CK_ATTRIBUTE_PTR two)
+{
+ assert (one);
+ assert (two);
+
+ if (one->type != two->type)
+ return 0;
+ if (one->ulValueLen != two->ulValueLen)
+ return 0;
+ if (one->pValue == two->pValue)
+ return 1;
+ if (!one->pValue || !two->pValue)
+ return 0;
+ return memcmp (one->pValue, two->pValue, one->ulValueLen) == 0;
+}
+
+int
+p11_kit_uri_match_attributes (P11KitUri *uri, CK_ATTRIBUTE_PTR attrs,
+ CK_ULONG n_attrs)
+{
+ CK_ULONG j;
+ int i;
+
+ assert (uri);
+ assert (attrs || !n_attrs);
+
+ if (uri->unrecognized)
+ return 0;
+
+ for (i = 0; i < NUM_ATTRS; ++i) {
+ if (uri->attrs[i].ulValueLen == (CK_ULONG)-1)
+ continue;
+ for (j = 0; j < n_attrs; ++j) {
+ if (attrs[j].type == uri->attrs[i].type) {
+ if (!match_attributes (&uri->attrs[i], &attrs[j]))
+ return 0;
+ break;
+ }
+ }
+ }
+
+ return 1;
+}
+
+void
+p11_kit_uri_set_unrecognized (P11KitUri *uri, int unrecognized)
+{
+ assert (uri);
+ uri->unrecognized = unrecognized;
+}
+
+int
+p11_kit_uri_any_unrecognized (P11KitUri *uri)
+{
+ assert (uri);
+ return uri->unrecognized;
+}
+
+P11KitUri*
+p11_kit_uri_new (void)
+{
+ P11KitUri *uri;
+ int i;
+
+ uri = calloc (1, sizeof (P11KitUri));
+ if (!uri)
+ return NULL;
+
+ /* So that it matches anything */
+ uri->module.libraryVersion.major = (CK_BYTE)-1;
+ uri->module.libraryVersion.minor = (CK_BYTE)-1;
+
+ for (i = 0; i < NUM_ATTRS; ++i) {
+ uri->attrs[i].type = idx_to_attribute (i);
+ uri->attrs[i].ulValueLen = (CK_ULONG)-1;
+ }
+
+ return uri;
+}
+
+static size_t
+space_strlen (const unsigned char *string, size_t max_length)
+{
+ size_t i = max_length - 1;
+
+ assert (string);
+
+ while (i > 0 && string[i] == ' ')
+ --i;
+ return i + 1;
+}
+
+static int
+format_raw_string (char **string, size_t *length, int *is_first,
+ const char *name, const char *value)
+{
+ size_t namelen;
+ size_t vallen;
+
+ /* Not set */
+ if (!value)
+ return 1;
+
+ namelen = strlen (name);
+ vallen = strlen (value);
+
+ *string = xrealloc (*string, *length + namelen + vallen + 3);
+ if (!*string)
+ return 0;
+
+ if (!*is_first)
+ (*string)[(*length)++] = ';';
+ memcpy ((*string) + *length, name, namelen);
+ *length += namelen;
+ (*string)[(*length)++] = '=';
+ memcpy ((*string) + *length, value, vallen);
+ *length += vallen;
+ (*string)[*length] = 0;
+ *is_first = 0;
+
+ return 1;
+}
+
+
+static int
+format_struct_string (char **string, size_t *length, int *is_first,
+ const char *name, const unsigned char *value,
+ size_t value_max)
+{
+ char *encoded;
+ size_t len;
+ int ret;
+
+ /* Not set */
+ if (!value[0])
+ return 1;
+
+ len = space_strlen (value, value_max);
+ encoded = url_encode (value, value + len, NULL);
+ if (!encoded)
+ return 0;
+
+ ret = format_raw_string (string, length, is_first, name, encoded);
+ free (encoded);
+
+ return ret;
+}
+
+static int
+format_attribute_string (char **string, size_t *length, int *is_first,
+ const char *name, CK_ATTRIBUTE_PTR attr)
+{
+ unsigned char *value;
+ char *encoded;
+ int ret;
+
+ /* Not set */;
+ if (attr->ulValueLen == (CK_ULONG)-1)
+ return 1;
+
+ value = attr->pValue;
+ encoded = url_encode (value, value + attr->ulValueLen, NULL);
+ if (!encoded)
+ return 0;
+
+ ret = format_raw_string (string, length, is_first, name, encoded);
+ free (encoded);
+
+ return ret;
+}
+
+static int
+format_attribute_class (char **string, size_t *length, int *is_first,
+ const char *name, CK_ATTRIBUTE_PTR attr)
+{
+ CK_OBJECT_CLASS klass;
+ const char *value;
+
+ /* Not set */;
+ if (attr->ulValueLen != sizeof (klass))
+ return 1;
+
+ klass = *((CK_OBJECT_CLASS*)attr->pValue);
+ switch (klass) {
+ case CKO_DATA:
+ value = "data";
+ break;
+ case CKO_SECRET_KEY:
+ value = "secretkey";
+ break;
+ case CKO_CERTIFICATE:
+ value = "cert";
+ break;
+ case CKO_PUBLIC_KEY:
+ value = "public";
+ break;
+ case CKO_PRIVATE_KEY:
+ value = "private";
+ break;
+ }
+
+ return format_raw_string (string, length, is_first, name, value);
+}
+
+static int
+format_struct_version (char **string, size_t *length, int *is_first,
+ const char *name, CK_VERSION_PTR version)
+{
+ char buffer[64];
+
+ /* Not set */
+ if (version->major == (CK_BYTE)-1 && version->minor == (CK_BYTE)-1)
+ return 1;
+
+ snprintf (buffer, sizeof (buffer), "%d.%d",
+ (int)version->major, (int)version->minor);
+ return format_raw_string (string, length, is_first, name, buffer);
+}
+
+int
+p11_kit_uri_format (P11KitUri *uri, char **string)
+{
+ char *result = NULL;
+ size_t length = 0;
+ int is_first = 1;
+
+ result = malloc (128);
+ if (!result)
+ return P11_KIT_URI_NO_MEMORY;
+
+ length = P11_KIT_URI_PREFIX_LEN;
+ memcpy (result, P11_KIT_URI_PREFIX, length);
+ result[length] = 0;
+
+ if (!format_struct_string (&result, &length, &is_first, "library-description",
+ uri->module.libraryDescription,
+ sizeof (uri->module.libraryDescription)) ||
+ !format_struct_string (&result, &length, &is_first, "library-manufacturer",
+ uri->module.manufacturerID,
+ sizeof (uri->module.manufacturerID)) ||
+ !format_struct_string (&result, &length, &is_first, "model",
+ uri->token.model,
+ sizeof (uri->token.model)) ||
+ !format_struct_string (&result, &length, &is_first, "manufacturer",
+ uri->token.manufacturerID,
+ sizeof (uri->token.manufacturerID)) ||
+ !format_struct_string (&result, &length, &is_first, "serial",
+ uri->token.serialNumber,
+ sizeof (uri->token.serialNumber)) ||
+ !format_struct_string (&result, &length, &is_first, "token",
+ uri->token.label,
+ sizeof (uri->token.label)) ||
+ !format_struct_version (&result, &length, &is_first, "library-version",
+ &uri->module.libraryVersion)) {
+ free (result);
+ return P11_KIT_URI_NO_MEMORY;
+ }
+
+ if (!format_attribute_string (&result, &length, &is_first, "id",
+ &uri->attrs[ID_IDX]) ||
+ !format_attribute_string (&result, &length, &is_first, "object",
+ &uri->attrs[LABEL_IDX])) {
+ free (result);
+ return P11_KIT_URI_NO_MEMORY;
+ }
+
+ if (!format_attribute_class (&result, &length, &is_first, "objecttype",
+ &uri->attrs[CLASS_IDX])) {
+ free (result);
+ return P11_KIT_URI_NO_MEMORY;
+ }
+
+ *string = result;
+ return P11_KIT_URI_OK;
+}
+
+static int
+parse_string_attribute (const char *name, const char *start, const char *end,
+ P11KitUri *uri)
+{
+ unsigned char *value;
+ size_t length;
+ int idx, ret;
+
+ assert (start <= end);
+
+ if (strcmp ("id", name) == 0)
+ idx = ID_IDX;
+ else if (strcmp ("object", name) == 0)
+ idx = LABEL_IDX;
+ else
+ return 0;
+
+ ret = url_decode (start, end, &value, &length);
+ if (ret < 0)
+ return ret;
+
+ free (uri->attrs[idx].pValue);
+ uri->attrs[idx].pValue = value;
+ uri->attrs[idx].ulValueLen = length;
+ return 1;
+}
+
+static int
+equals_segment (const char *start, const char *end, const char *match)
+{
+ size_t len = strlen (match);
+ assert (start <= end);
+ return (end - start == len) && memcmp (start, match, len) == 0;
+}
+
+static int
+parse_class_attribute (const char *name, const char *start, const char *end,
+ P11KitUri *uri)
+{
+ CK_OBJECT_CLASS klass = 0;
+ void *value;
+
+ assert (start <= end);
+
+ if (strcmp ("objecttype", name) != 0)
+ return 0;
+
+ if (equals_segment (start, end, "cert"))
+ klass = CKO_CERTIFICATE;
+ else if (equals_segment (start, end, "public"))
+ klass = CKO_PUBLIC_KEY;
+ else if (equals_segment (start, end, "private"))
+ klass = CKO_PRIVATE_KEY;
+ else if (equals_segment (start, end, "secretkey"))
+ klass = CKO_SECRET_KEY;
+ else if (equals_segment (start, end, "data"))
+ klass = CKO_DATA;
+ else {
+ uri->unrecognized = 1;
+ return 1;
+ }
+
+ value = malloc (sizeof (klass));
+ if (value == NULL)
+ return P11_KIT_URI_NO_MEMORY;
+
+ free (uri->attrs[CLASS_IDX].pValue);
+ memcpy (value, &klass, sizeof (klass));
+ uri->attrs[CLASS_IDX].pValue = value;
+ uri->attrs[CLASS_IDX].ulValueLen = sizeof (klass);
+
+ return 1;
+}
+
+static int
+parse_struct_info (unsigned char *where, size_t length, const char *start,
+ const char *end, P11KitUri *uri)
+{
+ unsigned char *value;
+ size_t value_length;
+ int ret;
+
+ assert (start <= end);
+
+ ret = url_decode (start, end, &value, &value_length);
+ if (ret < 0)
+ return ret;
+
+ /* Too long, shouldn't match anything */
+ if (value_length > length) {
+ free (value);
+ uri->unrecognized = 1;
+ return 1;
+ }
+
+ memset (where, ' ', length);
+ memcpy (where, value, value_length);
+
+ free (value);
+ return 1;
+}
+
+static int
+parse_token_info (const char *name, const char *start, const char *end,
+ P11KitUri *uri)
+{
+ unsigned char *where;
+ size_t length;
+
+ assert (start <= end);
+
+ if (strcmp (name, "model") == 0) {
+ where = uri->token.model;
+ length = sizeof (uri->token.model);
+ } else if (strcmp (name, "manufacturer") == 0) {
+ where = uri->token.manufacturerID;
+ length = sizeof (uri->token.manufacturerID);
+ } else if (strcmp (name, "serial") == 0) {
+ where = uri->token.serialNumber;
+ length = sizeof (uri->token.serialNumber);
+ } else if (strcmp (name, "token") == 0) {
+ where = uri->token.label;
+ length = sizeof (uri->token.label);
+ } else {
+ return 0;
+ }
+
+ return parse_struct_info (where, length, start, end, uri);
+}
+
+static int
+atoin (const char *start, const char *end)
+{
+ int ret = 0;
+ while (start != end) {
+ if (*start < '0' || *start > '9')
+ return -1;
+ ret *= 10;
+ ret += (*start - '0');
+ ++start;
+ }
+ return ret;
+}
+
+static int
+parse_struct_version (const char *start, const char *end, CK_VERSION_PTR version)
+{
+ const char *dot;
+ int val;
+
+ assert (start <= end);
+
+ dot = memchr (start, '.', end - start);
+ if (!dot)
+ dot = end;
+
+ if (dot == start)
+ return P11_KIT_URI_BAD_VERSION;
+ val = atoin (start, dot);
+ if (val < 0 || val >= 255)
+ return P11_KIT_URI_BAD_VERSION;
+ version->major = (CK_BYTE)val;
+ version->minor = 0;
+
+ if (dot != end) {
+ if (dot + 1 == end)
+ return P11_KIT_URI_BAD_VERSION;
+ val = atoin (dot + 1, end);
+ if (val < 0 || val >= 255)
+ return P11_KIT_URI_BAD_VERSION;
+ version->minor = (CK_BYTE)val;
+ }
+
+ return 1;
+}
+
+static int
+parse_module_info (const char *name, const char *start, const char *end,
+ P11KitUri *uri)
+{
+ unsigned char *where;
+ size_t length;
+
+ assert (start <= end);
+
+ if (strcmp (name, "library-description") == 0) {
+ where = uri->module.libraryDescription;
+ length = sizeof (uri->module.libraryDescription);
+ } else if (strcmp (name, "library-manufacturer") == 0) {
+ where = uri->module.manufacturerID;
+ length = sizeof (uri->module.manufacturerID);
+ } else if (strcmp (name, "library-version") == 0) {
+ return parse_struct_version (start, end,
+ &uri->module.libraryVersion);
+ } else {
+ return 0;
+ }
+
+ return parse_struct_info (where, length, start, end, uri);
+}
+
+int
+p11_kit_uri_parse (const char *string, P11KitUriContext context,
+ P11KitUri *uri)
+{
+ const char *spos, *epos;
+ char *key = NULL;
+ int ret = -1;
+ int i;
+
+ assert (string);
+ assert (uri);
+
+ if (strncmp (string, P11_KIT_URI_PREFIX, P11_KIT_URI_PREFIX_LEN) != 0)
+ return P11_KIT_URI_BAD_PREFIX;
+
+ string += P11_KIT_URI_PREFIX_LEN;
+
+ /* Clear everything out */
+ memset (&uri->module, 0, sizeof (uri->module));
+ memset (&uri->token, 0, sizeof (uri->module));
+ for (i = 0; i < NUM_ATTRS; ++i)
+ uri->attrs[i].ulValueLen = (CK_ULONG)-1;
+ uri->module.libraryVersion.major = (CK_BYTE)-1;
+ uri->module.libraryVersion.minor = (CK_BYTE)-1;
+ uri->unrecognized = 0;
+
+ for (;;) {
+ spos = strchr (string, ';');
+ if (spos == NULL) {
+ spos = string + strlen (string);
+ assert (*spos == '\0');
+ if (spos == string)
+ break;
+ }
+
+ epos = strchr (string, '=');
+ if (epos == NULL || spos == string || epos == string || epos >= spos)
+ return P11_KIT_URI_BAD_SYNTAX;
+
+ key = malloc ((epos - string) + 1);
+ if (key == NULL)
+ return P11_KIT_URI_NO_MEMORY;
+ memcpy (key, string, epos - string);
+ key[epos - string] = 0;
+ epos++;
+
+ ret = 0;
+ if (context & P11_KIT_URI_PARSE_OBJECT)
+ ret = parse_string_attribute (key, epos, spos, uri);
+ if (ret == 0 && context & P11_KIT_URI_PARSE_OBJECT)
+ ret = parse_class_attribute (key, epos, spos, uri);
+ if (ret == 0 && context & P11_KIT_URI_PARSE_TOKEN)
+ ret = parse_token_info (key, epos, spos, uri);
+ if (ret == 0 && context & P11_KIT_URI_PARSE_MODULE)
+ ret = parse_module_info (key, epos, spos, uri);
+ free (key);
+
+ if (ret < 0)
+ return ret;
+ if (ret == 0)
+ uri->unrecognized = 1;
+
+ if (*spos == '\0')
+ break;
+ string = spos + 1;
+ }
+
+ return P11_KIT_URI_OK;
+}
+
+void
+p11_kit_uri_free (P11KitUri *uri)
+{
+ int i;
+
+ if (!uri)
+ return;
+
+ for (i = 0; i < NUM_ATTRS; ++i)
+ free (uri->attrs[i].pValue);
+
+ free (uri);
+}
diff --git a/module/p11-kit-uri.h b/module/p11-kit-uri.h
new file mode 100644
index 0000000..c5e86bb
--- /dev/null
+++ b/module/p11-kit-uri.h
@@ -0,0 +1,101 @@
+/*
+ * 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 "pkcs11.h"
+
+#ifndef __P11_KIT_URI_H__
+#define __P11_KIT_URI_H__
+
+#define P11_KIT_URI_PREFIX "pkcs11:"
+#define P11_KIT_URI_PREFIX_LEN 7
+
+typedef enum {
+ P11_KIT_URI_OK = 0,
+ P11_KIT_URI_NO_MEMORY = -1,
+ P11_KIT_URI_BAD_PREFIX = -2,
+ P11_KIT_URI_BAD_ENCODING = -3,
+ P11_KIT_URI_BAD_SYNTAX = -4,
+ P11_KIT_URI_BAD_VERSION = -5,
+ P11_KIT_URI_NOT_FOUND = -6,
+} P11KitUriParseStatus;
+
+typedef enum {
+ P11_KIT_URI_PARSE_MODULE = (1 << 1),
+ P11_KIT_URI_PARSE_TOKEN = (1 << 2) | P11_KIT_URI_PARSE_MODULE,
+ P11_KIT_URI_PARSE_OBJECT = (1 << 3) | P11_KIT_URI_PARSE_TOKEN,
+ P11_KIT_URI_PARSE_ANY = 0xFFFFFFFF,
+} P11KitUriContext;
+
+typedef struct _P11KitUri P11KitUri;
+
+CK_INFO_PTR p11_kit_uri_get_module_info (P11KitUri *uri);
+
+int p11_kit_uri_match_module_info (P11KitUri *uri,
+ CK_INFO_PTR info);
+
+CK_TOKEN_INFO_PTR p11_kit_uri_get_token_info (P11KitUri *uri);
+
+int p11_kit_uri_match_token_info (P11KitUri *uri,
+ CK_TOKEN_INFO_PTR token_info);
+
+CK_ATTRIBUTE_PTR p11_kit_uri_get_attribute (P11KitUri *uri,
+ CK_ATTRIBUTE_TYPE type);
+
+int p11_kit_uri_set_attribute (P11KitUri *uri,
+ CK_ATTRIBUTE_PTR attr);
+
+int p11_kit_uri_clear_attribute (P11KitUri *uri,
+ CK_ATTRIBUTE_TYPE type);
+
+int p11_kit_uri_match_attributes (P11KitUri *uri,
+ CK_ATTRIBUTE_PTR attrs,
+ CK_ULONG n_attrs);
+
+void p11_kit_uri_set_unrecognized (P11KitUri *uri,
+ int unrecognized);
+
+int p11_kit_uri_any_unrecognized (P11KitUri *uri);
+
+P11KitUri* p11_kit_uri_new (void);
+
+int p11_kit_uri_format (P11KitUri *uri,
+ char **string);
+
+int p11_kit_uri_parse (const char *string,
+ P11KitUriContext context,
+ P11KitUri *uri);
+
+void p11_kit_uri_free (P11KitUri *uri);
+
+#endif /* __P11_KIT_URI_H__ */
diff --git a/module/p11-kit.h b/module/p11-kit.h
index 50b93d8..25af193 100644
--- a/module/p11-kit.h
+++ b/module/p11-kit.h
@@ -35,6 +35,8 @@
#ifndef __P11_KIT_H__
#define __P11_KIT_H__
+#include "pkcs11.h"
+
CK_RV p11_kit_initialize_registered (void);
CK_RV p11_kit_finalize_registered (void);
diff --git a/module/util.c b/module/util.c
new file mode 100644
index 0000000..516e70b
--- /dev/null
+++ b/module/util.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2011 Collabora Ltd
+ * All rights reserved.
+ *
+ * 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.
+ *
+ *
+ * CONTRIBUTORS
+ * Stef Walter <stef@memberwebs.com>
+ */
+
+#include "config.h"
+
+#include "util.h"
+
+#include <stdlib.h>
+
+void*
+xrealloc (void *memory, size_t length)
+{
+ void *allocated = realloc (memory, length);
+ if (!allocated)
+ free (memory);
+ return allocated;
+}
diff --git a/module/util.h b/module/util.h
new file mode 100644
index 0000000..73f06ec
--- /dev/null
+++ b/module/util.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Collabora Ltd
+ * All rights reserved.
+ *
+ * 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.
+ *
+ *
+ * CONTRIBUTORS
+ * Stef Walter <stef@memberwebs.com>
+ */
+
+#ifndef __UTIL_H__
+#define __UTIL_H__
+
+#include <sys/types.h>
+
+void* xrealloc (void *memory, size_t length);
+
+#endif /* __UTIL_H__ */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5c9e0e4..92dba16 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -7,7 +7,8 @@ INCLUDES = \
noinst_PROGRAMS = \
hash-test \
- conf-test
+ conf-test \
+ uri-test
hash_test_LDADD = \
$(top_builddir)/module/libp11-kit-testable.la
@@ -15,6 +16,10 @@ hash_test_LDADD = \
conf_test_LDADD = \
$(top_builddir)/module/libp11-kit-testable.la
+uri_test_LDADD = \
+ $(top_builddir)/module/libp11-kit-testable.la
+
check-am:
./hash-test
./conf-test
+ ./uri-test \ No newline at end of file
diff --git a/tests/uri-test.c b/tests/uri-test.c
new file mode 100644
index 0000000..40e301a
--- /dev/null
+++ b/tests/uri-test.c
@@ -0,0 +1,1050 @@
+/*
+ * 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 <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "p11-kit-uri.h"
+
+static int
+is_module_empty (P11KitUri *uri)
+{
+ CK_INFO_PTR info = p11_kit_uri_get_module_info (uri);
+ return (info->libraryDescription[0] == 0 &&
+ info->manufacturerID[0] == 0 &&
+ info->libraryVersion.major == (CK_BYTE)-1 &&
+ info->libraryVersion.minor == (CK_BYTE)-1);
+}
+
+static int
+is_token_empty (P11KitUri *uri)
+{
+ CK_TOKEN_INFO_PTR token = p11_kit_uri_get_token_info (uri);
+ return (token->serialNumber[0] == 0 &&
+ token->manufacturerID[0] == 0 &&
+ token->label[0] == 0 &&
+ token->model[0] == 0);
+}
+
+static int
+are_attributes_empty (P11KitUri *uri)
+{
+ return (p11_kit_uri_get_attribute (uri, CKA_LABEL) == NULL &&
+ p11_kit_uri_get_attribute (uri, CKA_ID) == NULL &&
+ p11_kit_uri_get_attribute (uri, CKA_CLASS) == NULL);
+}
+
+static void
+test_uri_parse (CuTest *tc)
+{
+ P11KitUri *uri;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:", P11_KIT_URI_PARSE_MODULE, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ CuAssertTrue (tc, is_module_empty (uri));
+ CuAssertTrue (tc, is_token_empty (uri));
+ CuAssertTrue (tc, are_attributes_empty (uri));
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_parse_bad_scheme (CuTest *tc)
+{
+ P11KitUri *uri;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("http:\\example.com\test", P11_KIT_URI_PARSE_ANY, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_BAD_PREFIX, ret);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_parse_with_label (CuTest *tc)
+{
+ CK_ATTRIBUTE_PTR attr;
+ P11KitUri *uri;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:object=Test%20Label", P11_KIT_URI_PARSE_ANY, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ CuAssertTrue (tc, is_module_empty (uri));
+ CuAssertTrue (tc, is_token_empty (uri));
+
+ attr = p11_kit_uri_get_attribute (uri, CKA_LABEL);
+ CuAssertPtrNotNull (tc, attr);
+ CuAssertTrue (tc, attr->ulValueLen == strlen ("Test Label"));
+ CuAssertTrue (tc, memcmp (attr->pValue, "Test Label", attr->ulValueLen) == 0);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_parse_with_label_and_klass (CuTest *tc)
+{
+ CK_ATTRIBUTE_PTR attr;
+ P11KitUri *uri;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:object=Test%20Label;objecttype=cert", P11_KIT_URI_PARSE_ANY, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ attr = p11_kit_uri_get_attribute (uri, CKA_LABEL);
+ CuAssertPtrNotNull (tc, attr);
+ CuAssertTrue (tc, attr->ulValueLen == strlen ("Test Label"));
+ CuAssertTrue (tc, memcmp (attr->pValue, "Test Label", attr->ulValueLen) == 0);
+
+ attr = p11_kit_uri_get_attribute (uri, CKA_CLASS);
+ CuAssertPtrNotNull (tc, attr);
+ CuAssertTrue (tc, attr->ulValueLen == sizeof (CK_OBJECT_CLASS));
+ CuAssertTrue (tc, *((CK_OBJECT_CLASS_PTR)attr->pValue) == CKO_CERTIFICATE);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_parse_with_id (CuTest *tc)
+{
+ CK_ATTRIBUTE_PTR attr;
+ P11KitUri *uri;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:id=%54%45%53%54%00", P11_KIT_URI_PARSE_OBJECT, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ /* Note that there's a NULL in the attribute (end) */
+ attr = p11_kit_uri_get_attribute (uri, CKA_ID);
+ CuAssertPtrNotNull (tc, attr);
+ CuAssertTrue (tc, attr->ulValueLen == 5);
+ CuAssertTrue (tc, memcmp (attr->pValue, "TEST", 5) == 0);
+
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_parse_with_bad_string_encoding (CuTest *tc)
+{
+ P11KitUri *uri;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:object=Test%", P11_KIT_URI_PARSE_OBJECT, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_BAD_ENCODING, ret);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_parse_with_bad_hex_encoding (CuTest *tc)
+{
+ P11KitUri *uri;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:object=T%xxest", P11_KIT_URI_PARSE_OBJECT, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_BAD_ENCODING, ret);
+
+ p11_kit_uri_free (uri);
+}
+
+static int
+is_space_string (CK_UTF8CHAR_PTR string, CK_ULONG size, const char *check)
+{
+ size_t i, len = strlen (check);
+ if (len > size)
+ return 0;
+ if (memcmp (string, check, len) != 0)
+ return 0;
+ for (i = len; i < size; ++i)
+ if (string[i] != ' ')
+ return 0;
+ return 1;
+}
+
+static void
+test_uri_parse_with_token (CuTest *tc)
+{
+ P11KitUri *uri = NULL;
+ CK_TOKEN_INFO_PTR token;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:token=Token%20Label;serial=3333;model=Deluxe;manufacturer=Me",
+ P11_KIT_URI_PARSE_TOKEN, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ token = p11_kit_uri_get_token_info (uri);
+ CuAssertTrue (tc, is_space_string (token->label, sizeof (token->label), "Token Label"));
+ CuAssertTrue (tc, is_space_string (token->serialNumber, sizeof (token->serialNumber), "3333"));
+ CuAssertTrue (tc, is_space_string (token->model, sizeof (token->model), "Deluxe"));
+ CuAssertTrue (tc, is_space_string (token->manufacturerID, sizeof (token->manufacturerID), "Me"));
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_parse_with_token_bad_encoding (CuTest *tc)
+{
+ P11KitUri *uri;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:token=Token%", P11_KIT_URI_PARSE_TOKEN, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_BAD_ENCODING, ret);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_parse_with_bad_syntax (CuTest *tc)
+{
+ P11KitUri *uri;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:token", P11_KIT_URI_PARSE_ANY, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_BAD_SYNTAX, ret);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_parse_with_library (CuTest *tc)
+{
+ P11KitUri *uri = NULL;
+ CK_INFO_PTR info;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:library-description=The%20Library;library-manufacturer=Me",
+ P11_KIT_URI_PARSE_MODULE, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ info = p11_kit_uri_get_module_info (uri);
+
+ CuAssertTrue (tc, is_space_string (info->manufacturerID, sizeof (info->manufacturerID), "Me"));
+ CuAssertTrue (tc, is_space_string (info->libraryDescription, sizeof (info->libraryDescription), "The Library"));
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_parse_with_library_bad_encoding (CuTest *tc)
+{
+ P11KitUri *uri;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:library-description=Library%", P11_KIT_URI_PARSE_MODULE, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_BAD_ENCODING, ret);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_build_empty (CuTest *tc)
+{
+ P11KitUri *uri;
+ char *string;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_format (uri, &string);
+ CuAssertStrEquals (tc, "pkcs11:", string);
+ free (string);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+set_space_string (CK_BYTE_PTR buffer, CK_ULONG length, const char *string)
+{
+ size_t len = strlen (string);
+ assert (len <= length);
+ memset (buffer, ' ', length);
+ memcpy (buffer, string, len);
+}
+
+static void
+test_uri_build_with_token_info (CuTest *tc)
+{
+ char *string = NULL;
+ P11KitUri *uri;
+ P11KitUri *check;
+ CK_TOKEN_INFO_PTR token;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ token = p11_kit_uri_get_token_info (uri);
+ set_space_string (token->label, sizeof (token->label), "The Label");
+ set_space_string (token->serialNumber, sizeof (token->serialNumber), "44444");
+ set_space_string (token->manufacturerID, sizeof (token->manufacturerID), "Me");
+ set_space_string (token->model, sizeof (token->model), "Deluxe");
+
+ ret = p11_kit_uri_format (uri, &string);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+ CuAssertPtrNotNull (tc, string);
+
+ check = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, check);
+
+ ret = p11_kit_uri_parse (string, P11_KIT_URI_PARSE_TOKEN, check);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ p11_kit_uri_match_token_info (check, p11_kit_uri_get_token_info (uri));
+
+ p11_kit_uri_free (uri);
+ p11_kit_uri_free (check);
+
+ CuAssertTrue (tc, strstr (string, "token=The%20Label") != NULL);
+ CuAssertTrue (tc, strstr (string, "serial=44444") != NULL);
+ CuAssertTrue (tc, strstr (string, "manufacturer=Me") != NULL);
+ CuAssertTrue (tc, strstr (string, "model=Deluxe") != NULL);
+
+ free (string);
+}
+
+static void
+test_uri_build_with_token_null_info (CuTest *tc)
+{
+ char *string = NULL;
+ P11KitUri *uri;
+ CK_TOKEN_INFO_PTR token;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ token = p11_kit_uri_get_token_info (uri);
+ set_space_string (token->label, sizeof (token->label), "The Label");
+
+ ret = p11_kit_uri_format (uri, &string);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ CuAssertTrue (tc, strstr (string, "token=The%20Label") != NULL);
+ CuAssertTrue (tc, strstr (string, "serial=") == NULL);
+
+ free (string);
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_build_with_token_empty_info (CuTest *tc)
+{
+ char *string = NULL;
+ P11KitUri *uri;
+ CK_TOKEN_INFO_PTR token;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ token = p11_kit_uri_get_token_info (uri);
+ set_space_string (token->label, sizeof (token->label), "");
+ set_space_string (token->serialNumber, sizeof (token->serialNumber), "");
+
+ ret = p11_kit_uri_format (uri, &string);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ CuAssertTrue (tc, strstr (string, "token=") != NULL);
+ CuAssertTrue (tc, strstr (string, "serial=") != NULL);
+
+ free (string);
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_build_with_attributes (CuTest *tc)
+{
+ char *string = NULL;
+ P11KitUri *uri;
+ P11KitUri *check;
+ CK_OBJECT_CLASS klass;
+ CK_ATTRIBUTE_PTR attr;
+ CK_ATTRIBUTE at;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ at.type = CKA_LABEL;
+ at.pValue = "The Label";
+ at.ulValueLen = 9;
+ ret = p11_kit_uri_set_attribute (uri, &at);
+
+ at.type = CKA_ID;
+ at.pValue = "HELLO";
+ at.ulValueLen = 5;
+ ret = p11_kit_uri_set_attribute (uri, &at);
+
+ klass = CKO_DATA;
+ at.type = CKA_CLASS;
+ at.pValue = &klass;
+ at.ulValueLen = sizeof (klass);
+ ret = p11_kit_uri_set_attribute (uri, &at);
+
+ ret = p11_kit_uri_format (uri, &string);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ check = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, check);
+
+ ret = p11_kit_uri_parse (string, P11_KIT_URI_PARSE_ANY, check);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ attr = p11_kit_uri_get_attribute (check, CKA_LABEL);
+ CuAssertPtrNotNull (tc, attr);
+ CuAssertTrue (tc, attr->ulValueLen == 9);
+ CuAssertTrue (tc, memcmp (attr->pValue, "The Label", attr->ulValueLen) == 0);
+
+ attr = p11_kit_uri_get_attribute (check, CKA_CLASS);
+ CuAssertPtrNotNull (tc, attr);
+ CuAssertTrue (tc, attr->ulValueLen == sizeof (klass));
+ CuAssertTrue (tc, *((CK_OBJECT_CLASS_PTR)attr->pValue) == klass);
+
+ attr = p11_kit_uri_get_attribute (check, CKA_ID);
+ CuAssertPtrNotNull (tc, attr);
+ CuAssertTrue (tc, attr->ulValueLen == 5);
+ CuAssertTrue (tc, memcmp (attr->pValue, "HELLO", attr->ulValueLen) == 0);
+
+ p11_kit_uri_free (check);
+
+ CuAssertTrue (tc, strstr (string, "object=The%20Label") != NULL);
+ CuAssertTrue (tc, strstr (string, "objecttype=data") != NULL);
+ CuAssertTrue (tc, strstr (string, "id=HELLO") != NULL);
+
+ free (string);
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_parse_private_key (CuTest *tc)
+{
+ P11KitUri *uri;
+ CK_ATTRIBUTE_PTR attr;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:objecttype=private", P11_KIT_URI_PARSE_OBJECT, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ attr = p11_kit_uri_get_attribute (uri, CKA_CLASS);
+ CuAssertPtrNotNull (tc, attr);
+ CuAssertTrue (tc, attr->ulValueLen == sizeof (CK_OBJECT_CLASS));
+ CuAssertTrue (tc, *((CK_OBJECT_CLASS_PTR)attr->pValue) == CKO_PRIVATE_KEY);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_parse_secret_key (CuTest *tc)
+{
+ P11KitUri *uri;
+ CK_ATTRIBUTE_PTR attr;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:objecttype=secretkey", P11_KIT_URI_PARSE_OBJECT, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ attr = p11_kit_uri_get_attribute (uri, CKA_CLASS);
+ CuAssertPtrNotNull (tc, attr);
+ CuAssertTrue (tc, attr->ulValueLen == sizeof (CK_OBJECT_CLASS));
+ CuAssertTrue (tc, *((CK_OBJECT_CLASS_PTR)attr->pValue) == CKO_SECRET_KEY);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_parse_library_version (CuTest *tc)
+{
+ P11KitUri *uri;
+ CK_INFO_PTR info;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:library-version=2.101", P11_KIT_URI_PARSE_MODULE, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ info = p11_kit_uri_get_module_info (uri);
+ CuAssertIntEquals (tc, 2, info->libraryVersion.major);
+ CuAssertIntEquals (tc, 101, info->libraryVersion.minor);
+
+ ret = p11_kit_uri_parse ("pkcs11:library-version=23", P11_KIT_URI_PARSE_MODULE, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ info = p11_kit_uri_get_module_info (uri);
+ CuAssertIntEquals (tc, 23, info->libraryVersion.major);
+ CuAssertIntEquals (tc, 0, info->libraryVersion.minor);
+
+ ret = p11_kit_uri_parse ("pkcs11:library-version=23.", P11_KIT_URI_PARSE_MODULE, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_BAD_VERSION, ret);
+
+ ret = p11_kit_uri_parse ("pkcs11:library-version=a.a", P11_KIT_URI_PARSE_MODULE, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_BAD_VERSION, ret);
+
+ ret = p11_kit_uri_parse ("pkcs11:library-version=.23", P11_KIT_URI_PARSE_MODULE, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_BAD_VERSION, ret);
+
+ ret = p11_kit_uri_parse ("pkcs11:library-version=1000", P11_KIT_URI_PARSE_MODULE, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_BAD_VERSION, ret);
+
+ ret = p11_kit_uri_parse ("pkcs11:library-version=2.1000", P11_KIT_URI_PARSE_MODULE, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_BAD_VERSION, ret);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_parse_parse_unknown_objecttype (CuTest *tc)
+{
+ P11KitUri *uri;
+ CK_ATTRIBUTE_PTR attr;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:objecttype=unknown", P11_KIT_URI_PARSE_OBJECT, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ attr = p11_kit_uri_get_attribute (uri, CKA_CLASS);
+ CuAssertPtrEquals (tc, NULL, attr);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_parse_unrecognized (CuTest *tc)
+{
+ P11KitUri *uri;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:x-blah=some-value", P11_KIT_URI_PARSE_ANY, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ ret = p11_kit_uri_any_unrecognized (uri);
+ CuAssertIntEquals (tc, 1, ret);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_parse_too_long_is_unrecognized (CuTest *tc)
+{
+ P11KitUri *uri;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:model=a-value-that-is-too-long-for-the-field-that-it-goes-with",
+ P11_KIT_URI_PARSE_ANY, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ ret = p11_kit_uri_any_unrecognized (uri);
+ CuAssertIntEquals (tc, 1, ret);
+
+ p11_kit_uri_free (uri);
+}
+
+
+
+static void
+test_uri_build_objecttype_cert (CuTest *tc)
+{
+ CK_ATTRIBUTE attr;
+ CK_OBJECT_CLASS klass;
+ P11KitUri *uri;
+ char *string;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ klass = CKO_CERTIFICATE;
+ attr.type = CKA_CLASS;
+ attr.pValue = &klass;
+ attr.ulValueLen = sizeof (klass);
+ p11_kit_uri_set_attribute (uri, &attr);
+
+ ret = p11_kit_uri_format (uri, &string);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+ CuAssertTrue (tc, strstr (string, "objecttype=cert") != NULL);
+
+ p11_kit_uri_free (uri);
+ free (string);
+}
+
+static void
+test_uri_build_objecttype_private (CuTest *tc)
+{
+ CK_ATTRIBUTE attr;
+ CK_OBJECT_CLASS klass;
+ P11KitUri *uri;
+ char *string;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ klass = CKO_PRIVATE_KEY;
+ attr.type = CKA_CLASS;
+ attr.pValue = &klass;
+ attr.ulValueLen = sizeof (klass);
+ p11_kit_uri_set_attribute (uri, &attr);
+
+ ret = p11_kit_uri_format (uri, &string);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+ CuAssertTrue (tc, strstr (string, "objecttype=private") != NULL);
+
+ p11_kit_uri_free (uri);
+ free (string);
+}
+
+static void
+test_uri_build_objecttype_public (CuTest *tc)
+{
+ CK_ATTRIBUTE attr;
+ CK_OBJECT_CLASS klass;
+ P11KitUri *uri;
+ char *string;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ klass = CKO_PUBLIC_KEY;
+ attr.type = CKA_CLASS;
+ attr.pValue = &klass;
+ attr.ulValueLen = sizeof (klass);
+ p11_kit_uri_set_attribute (uri, &attr);
+
+ ret = p11_kit_uri_format (uri, &string);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+ CuAssertTrue (tc, strstr (string, "objecttype=public") != NULL);
+
+ p11_kit_uri_free (uri);
+ free (string);
+}
+
+static void
+test_uri_build_objecttype_secret (CuTest *tc)
+{
+ CK_ATTRIBUTE attr;
+ CK_OBJECT_CLASS klass;
+ P11KitUri *uri;
+ char *string;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ klass = CKO_SECRET_KEY;
+ attr.type = CKA_CLASS;
+ attr.pValue = &klass;
+ attr.ulValueLen = sizeof (klass);
+ p11_kit_uri_set_attribute (uri, &attr);
+
+ ret = p11_kit_uri_format (uri, &string);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+ CuAssertTrue (tc, strstr (string, "objecttype=secretkey") != NULL);
+
+ p11_kit_uri_free (uri);
+ free (string);
+}
+
+static void
+test_uri_build_with_library (CuTest *tc)
+{
+ CK_INFO_PTR info;
+ P11KitUri *uri;
+ char *string;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ info = p11_kit_uri_get_module_info (uri);
+ set_space_string (info->libraryDescription, sizeof (info->libraryDescription), "The Description");
+
+ ret = p11_kit_uri_format (uri, &string);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+ CuAssertTrue (tc, strstr (string, "library-description=The%20Description") != NULL);
+
+ p11_kit_uri_free (uri);
+ free (string);
+}
+
+static void
+test_uri_build_library_version (CuTest *tc)
+{
+ CK_INFO_PTR info;
+ P11KitUri *uri;
+ char *string;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ info = p11_kit_uri_get_module_info (uri);
+ info->libraryVersion.major = 2;
+ info->libraryVersion.minor = 10;
+
+ ret = p11_kit_uri_format (uri, &string);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+ CuAssertTrue (tc, strstr (string, "library-version=2.10") != NULL);
+
+ p11_kit_uri_free (uri);
+ free (string);
+}
+
+static void
+test_uri_get_set_unrecognized (CuTest *tc)
+{
+ P11KitUri *uri;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_any_unrecognized (uri);
+ CuAssertIntEquals (tc, 0, ret);
+
+ p11_kit_uri_set_unrecognized (uri, 1);
+
+ ret = p11_kit_uri_any_unrecognized (uri);
+ CuAssertIntEquals (tc, 1, ret);
+
+ p11_kit_uri_set_unrecognized (uri, 0);
+
+ ret = p11_kit_uri_any_unrecognized (uri);
+ CuAssertIntEquals (tc, 0, ret);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_match_token (CuTest *tc)
+{
+ CK_TOKEN_INFO token;
+ P11KitUri *uri;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:model=Giselle", P11_KIT_URI_PARSE_ANY, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ set_space_string (token.label, sizeof (token.label), "A label");
+ set_space_string (token.model, sizeof (token.model), "Giselle");
+
+ ret = p11_kit_uri_match_token_info (uri, &token);
+ CuAssertIntEquals (tc, 1, ret);
+
+ set_space_string (token.label, sizeof (token.label), "Another label");
+
+ ret = p11_kit_uri_match_token_info (uri, &token);
+ CuAssertIntEquals (tc, 1, ret);
+
+ set_space_string (token.model, sizeof (token.model), "Zoolander");
+
+ ret = p11_kit_uri_match_token_info (uri, &token);
+ CuAssertIntEquals (tc, 0, ret);
+
+ p11_kit_uri_set_unrecognized (uri, 1);
+
+ ret = p11_kit_uri_match_token_info (uri, &token);
+ CuAssertIntEquals (tc, 0, ret);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_match_module (CuTest *tc)
+{
+ CK_INFO info;
+ P11KitUri *uri;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:library-description=Quiet", P11_KIT_URI_PARSE_ANY, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ set_space_string (info.libraryDescription, sizeof (info.libraryDescription), "Quiet");
+ set_space_string (info.manufacturerID, sizeof (info.manufacturerID), "Someone");
+
+ ret = p11_kit_uri_match_module_info (uri, &info);
+ CuAssertIntEquals (tc, 1, ret);
+
+ set_space_string (info.manufacturerID, sizeof (info.manufacturerID), "Someone else");
+
+ ret = p11_kit_uri_match_module_info (uri, &info);
+ CuAssertIntEquals (tc, 1, ret);
+
+ set_space_string (info.libraryDescription, sizeof (info.libraryDescription), "Leise");
+
+ ret = p11_kit_uri_match_module_info (uri, &info);
+ CuAssertIntEquals (tc, 0, ret);
+
+ p11_kit_uri_set_unrecognized (uri, 1);
+
+ ret = p11_kit_uri_match_module_info (uri, &info);
+ CuAssertIntEquals (tc, 0, ret);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_match_attributes (CuTest *tc)
+{
+ CK_ATTRIBUTE attrs[4];
+ CK_OBJECT_CLASS klass;
+ P11KitUri *uri;
+ int ret;
+
+ attrs[0].type = CKA_ID;
+ attrs[0].pValue = "Blah";
+ attrs[0].ulValueLen = 4;
+
+ attrs[1].type = CKA_LABEL;
+ attrs[1].pValue = "Junk";
+ attrs[1].ulValueLen = 4;
+
+ attrs[2].type = CKA_COLOR;
+ attrs[2].pValue = "blue";
+ attrs[2].ulValueLen = 4;
+
+ klass = CKO_DATA;
+ attrs[3].type = CKA_CLASS;
+ attrs[3].pValue = &klass;
+ attrs[3].ulValueLen = sizeof (klass);
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ret = p11_kit_uri_parse ("pkcs11:object=Fancy;id=Blah;objecttype=data", P11_KIT_URI_PARSE_ANY, uri);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ ret = p11_kit_uri_match_attributes (uri, attrs, 4);
+ CuAssertIntEquals (tc, 0, ret);
+
+ attrs[1].pValue = "Fancy";
+ attrs[1].ulValueLen = 5;
+
+ ret = p11_kit_uri_match_attributes (uri, attrs, 4);
+ CuAssertIntEquals (tc, 1, ret);
+
+ p11_kit_uri_clear_attribute (uri, CKA_CLASS);
+
+ ret = p11_kit_uri_match_attributes (uri, attrs, 4);
+ CuAssertIntEquals (tc, 1, ret);
+
+ attrs[2].pValue = "pink";
+
+ ret = p11_kit_uri_match_attributes (uri, attrs, 4);
+ CuAssertIntEquals (tc, 1, ret);
+
+ p11_kit_uri_set_unrecognized (uri, 1);
+
+ ret = p11_kit_uri_match_attributes (uri, attrs, 4);
+ CuAssertIntEquals (tc, 0, ret);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_get_set_attribute (CuTest *tc)
+{
+ CK_ATTRIBUTE attr;
+ CK_ATTRIBUTE_PTR ptr;
+ P11KitUri *uri;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ CuAssertPtrNotNull (tc, uri);
+
+ ptr = p11_kit_uri_get_attribute (uri, CKA_LABEL);
+ CuAssertPtrEquals (tc, NULL, ptr);
+
+ ret = p11_kit_uri_clear_attribute (uri, CKA_LABEL);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ ret = p11_kit_uri_clear_attribute (uri, CKA_COLOR);
+ CuAssertIntEquals (tc, P11_KIT_URI_NOT_FOUND, ret);
+
+ attr.type = CKA_LABEL;
+ attr.pValue = "Test";
+ attr.ulValueLen = 4;
+
+ ret = p11_kit_uri_set_attribute (uri, &attr);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ attr.type = CKA_COLOR;
+ ret = p11_kit_uri_set_attribute (uri, &attr);
+ CuAssertIntEquals (tc, P11_KIT_URI_NOT_FOUND, ret);
+
+ ptr = p11_kit_uri_get_attribute (uri, CKA_COLOR);
+ CuAssertPtrEquals (tc, NULL, ptr);
+
+ ptr = p11_kit_uri_get_attribute (uri, CKA_LABEL);
+ CuAssertPtrNotNull (tc, ptr);
+
+ CuAssertTrue (tc, ptr->type == CKA_LABEL);
+ CuAssertTrue (tc, ptr->ulValueLen == 4);
+ CuAssertTrue (tc, memcmp (ptr->pValue, "Test", 4) == 0);
+
+ ret = p11_kit_uri_clear_attribute (uri, CKA_LABEL);
+ CuAssertIntEquals (tc, P11_KIT_URI_OK, ret);
+
+ ptr = p11_kit_uri_get_attribute (uri, CKA_LABEL);
+ CuAssertPtrEquals (tc, NULL, ptr);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
+test_uri_free_null (CuTest *tc)
+{
+ p11_kit_uri_free (NULL);
+}
+
+int
+main (void)
+{
+ CuString *output = CuStringNew ();
+ CuSuite* suite = CuSuiteNew ();
+ int ret;
+
+ SUITE_ADD_TEST (suite, test_uri_parse);
+ SUITE_ADD_TEST (suite, test_uri_parse_bad_scheme);
+ SUITE_ADD_TEST (suite, test_uri_parse_with_label);
+ SUITE_ADD_TEST (suite, test_uri_parse_with_label_and_klass);
+ SUITE_ADD_TEST (suite, test_uri_parse_with_id);
+ SUITE_ADD_TEST (suite, test_uri_parse_with_bad_string_encoding);
+ SUITE_ADD_TEST (suite, test_uri_parse_with_bad_hex_encoding);
+ SUITE_ADD_TEST (suite, test_uri_parse_with_token);
+ SUITE_ADD_TEST (suite, test_uri_parse_with_token_bad_encoding);
+ SUITE_ADD_TEST (suite, test_uri_parse_with_bad_syntax);
+ SUITE_ADD_TEST (suite, test_uri_parse_with_library);
+ SUITE_ADD_TEST (suite, test_uri_parse_with_library_bad_encoding);
+ SUITE_ADD_TEST (suite, test_uri_build_empty);
+ SUITE_ADD_TEST (suite, test_uri_build_with_token_info);
+ SUITE_ADD_TEST (suite, test_uri_build_with_token_null_info);
+ SUITE_ADD_TEST (suite, test_uri_build_with_token_empty_info);
+ SUITE_ADD_TEST (suite, test_uri_build_with_attributes);
+ SUITE_ADD_TEST (suite, test_uri_parse_private_key);
+ SUITE_ADD_TEST (suite, test_uri_parse_secret_key);
+ SUITE_ADD_TEST (suite, test_uri_parse_library_version);
+ SUITE_ADD_TEST (suite, test_uri_parse_parse_unknown_objecttype);
+ SUITE_ADD_TEST (suite, test_uri_parse_unrecognized);
+ SUITE_ADD_TEST (suite, test_uri_parse_too_long_is_unrecognized);
+ SUITE_ADD_TEST (suite, test_uri_build_objecttype_cert);
+ SUITE_ADD_TEST (suite, test_uri_build_objecttype_private);
+ SUITE_ADD_TEST (suite, test_uri_build_objecttype_public);
+ SUITE_ADD_TEST (suite, test_uri_build_objecttype_secret);
+ SUITE_ADD_TEST (suite, test_uri_build_with_library);
+ SUITE_ADD_TEST (suite, test_uri_build_library_version);
+ SUITE_ADD_TEST (suite, test_uri_get_set_unrecognized);
+ SUITE_ADD_TEST (suite, test_uri_match_token);
+ SUITE_ADD_TEST (suite, test_uri_match_module);
+ SUITE_ADD_TEST (suite, test_uri_match_attributes);
+ SUITE_ADD_TEST (suite, test_uri_get_set_attribute);
+ SUITE_ADD_TEST (suite, test_uri_free_null);
+
+ CuSuiteRun (suite);
+ CuSuiteSummary (suite, output);
+ CuSuiteDetails (suite, output);
+ printf ("%s\n", output->buffer);
+ ret = suite->failCount;
+ CuSuiteDelete (suite);
+ return ret;
+}
+
+#include "CuTest.c"