summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2017-02-20 11:01:21 +0100
committerDaiki Ueno <ueno@gnu.org>2017-02-21 17:46:04 +0100
commit1e80b5858a90497879e1e3faee4c7f76d5cbd6f0 (patch)
tree017dcd75b4e170959c94a0fd7721a69f44468b2a
parenteb65a85a4abfbab489f271c9f074409ba46ce8f5 (diff)
uri: Support vendor query attributes
If an unknown attribute is present in the query part of the PKCS#11 URI, the parser treated it as unrecognized and subsequent matches failed. Instead, keep track of such attributes and provide a set of API to deal with them.
-rw-r--r--doc/manual/p11-kit-sections.txt2
-rw-r--r--p11-kit/test-uri.c40
-rw-r--r--p11-kit/uri.c100
-rw-r--r--p11-kit/uri.h6
4 files changed, 146 insertions, 2 deletions
diff --git a/doc/manual/p11-kit-sections.txt b/doc/manual/p11-kit-sections.txt
index a1fdeb5..c1c1df1 100644
--- a/doc/manual/p11-kit-sections.txt
+++ b/doc/manual/p11-kit-sections.txt
@@ -34,6 +34,8 @@ p11_kit_uri_get_module_name
p11_kit_uri_set_module_name
p11_kit_uri_get_module_path
p11_kit_uri_set_module_path
+p11_kit_uri_get_vendor_query
+p11_kit_uri_set_vendor_query
p11_kit_uri_format
p11_kit_uri_parse
p11_kit_uri_free
diff --git a/p11-kit/test-uri.c b/p11-kit/test-uri.c
index db694a7..931c135 100644
--- a/p11-kit/test-uri.c
+++ b/p11-kit/test-uri.c
@@ -1507,6 +1507,45 @@ test_uri_module_name_and_path (void)
}
static void
+test_uri_vendor_query (void)
+{
+ P11KitUri *uri;
+ const char *value;
+ char *string;
+ int ret;
+
+ uri = p11_kit_uri_new ();
+ assert_ptr_not_null (uri);
+
+ ret = p11_kit_uri_set_vendor_query (uri, "my-query-one", "123456");
+ assert_num_eq (1, ret);
+ value = p11_kit_uri_get_vendor_query (uri, "my-query-one");
+ assert_str_eq ("123456", value);
+
+ ret = p11_kit_uri_format (uri, P11_KIT_URI_FOR_ANY, &string);
+ assert_num_eq (P11_KIT_URI_OK, ret);
+ assert (strstr (string, "my-query-one=123456") != NULL);
+ free (string);
+
+ ret = p11_kit_uri_parse ("pkcs11:?my-query-two=some-value", P11_KIT_URI_FOR_ANY, uri);
+ assert_num_eq (P11_KIT_URI_OK, ret);
+
+ value = p11_kit_uri_get_vendor_query (uri, "my-query-two");
+ assert_str_eq ("some-value", value);
+
+ ret = p11_kit_uri_set_vendor_query (uri, "my-query-two", "other-value");
+ assert_num_eq (1, ret);
+
+ value = p11_kit_uri_get_vendor_query (uri, "my-query-two");
+ assert_str_eq ("other-value", value);
+
+ ret = p11_kit_uri_set_vendor_query (uri, "my-query-three", NULL);
+ assert_num_eq (0, ret);
+
+ p11_kit_uri_free (uri);
+}
+
+static void
test_uri_slot_id (void)
{
P11KitUri *uri;
@@ -1618,6 +1657,7 @@ main (int argc,
p11_test (test_uri_module_name_bad, "/uri/module-name-bad");
p11_test (test_uri_module_path, "/uri/module-path");
p11_test (test_uri_module_name_and_path, "/uri/module-name-and-path");
+ p11_test (test_uri_vendor_query, "/uri/vendor-query");
p11_test (test_uri_slot_id, "/uri/slot-id");
p11_test (test_uri_slot_id_bad, "/uri/slot-id-bad");
p11_test (test_uri_free_null, "/uri/test_uri_free_null");
diff --git a/p11-kit/uri.c b/p11-kit/uri.c
index 5a3e19e..a61daef 100644
--- a/p11-kit/uri.c
+++ b/p11-kit/uri.c
@@ -38,6 +38,7 @@
#include "buffer.h"
#define P11_DEBUG_FLAG P11_DEBUG_URI
#include "debug.h"
+#include "dict.h"
#include "message.h"
#include "pkcs11.h"
#include "private.h"
@@ -150,6 +151,7 @@ struct p11_kit_uri {
char *pin_value;
char *module_name;
char *module_path;
+ p11_dict *qattrs;
};
static char *
@@ -795,6 +797,49 @@ p11_kit_uri_set_module_path (P11KitUri *uri, const char *path)
}
/**
+ * p11_kit_uri_get_vendor_query:
+ * @uri: The URI
+ * @name: The name of vendor query
+ *
+ * Get the vendor query part of the URI, identified by @name. This is
+ * used by some applications to explicitly specify the path of a
+ * PKCS\#11 module.
+ *
+ * Returns: The value of vendor query or %NULL if not present.
+ */
+const char*
+p11_kit_uri_get_vendor_query (P11KitUri *uri, const char *name)
+{
+ return_val_if_fail (uri != NULL, NULL);
+ return p11_dict_get (uri->qattrs, name);
+}
+
+/**
+ * p11_kit_uri_set_vendor_query:
+ * @uri: The URI
+ * @name: The name of vendor query
+ * @value: (allow-none): The value of vendor query
+ *
+ * Set the vendor query part of the URI, identified by @name. This is
+ * used by some applications to explicitly specify the path of a
+ * PKCS\#11 module.
+ *
+ * Returns: 1 if the vendor query is set or removed, 0 if not.
+ */
+int
+p11_kit_uri_set_vendor_query (P11KitUri *uri, const char *name,
+ const char *value)
+{
+ return_val_if_fail (uri != NULL, 0);
+ return_val_if_fail (name != NULL, 0);
+
+ if (value == NULL)
+ return p11_dict_remove (uri->qattrs, name);
+
+ return p11_dict_set (uri->qattrs, strdup (name), strdup (value));
+}
+
+/**
* p11_kit_uri_new:
*
* Create a new blank PKCS\#11 URI.
@@ -816,6 +861,7 @@ p11_kit_uri_new (void)
uri->module.libraryVersion.major = (CK_BYTE)-1;
uri->module.libraryVersion.minor = (CK_BYTE)-1;
uri->slot_id = (CK_SLOT_ID)-1;
+ uri->qattrs = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, free, free);
return uri;
}
@@ -1124,6 +1170,23 @@ p11_kit_uri_format (P11KitUri *uri, P11KitUriType uri_type, char **string)
}
}
+ if (uri->qattrs) {
+ p11_dictiter iter;
+ void *_key;
+ void *_value;
+
+ p11_dict_iterate (uri->qattrs, &iter);
+ while (p11_dict_next (&iter, &_key, &_value)) {
+ char *key = _key;
+ char *value = _value;
+ if (!format_encode_string (&buffer, &sep, key,
+ (const unsigned char *) value,
+ strlen (value), 0)) {
+ return_val_if_reached (P11_KIT_URI_UNEXPECTED);
+ }
+ }
+ }
+
return_val_if_fail (p11_buffer_ok (&buffer), P11_KIT_URI_UNEXPECTED);
*string = p11_buffer_steal (&buffer, NULL);
return P11_KIT_URI_OK;
@@ -1448,6 +1511,37 @@ parse_module_query (const char *name_start, const char *name_end,
return 0;
}
+static int
+parse_vendor_query (const char *name_start, const char *name_end,
+ const char *start, const char *end,
+ P11KitUri *uri)
+{
+ unsigned char *name;
+ unsigned char *value;
+
+ assert (name_start <= name_end);
+ assert (start <= end);
+
+ /* FIXME: Should we limit the characters in NAME, according to
+ * the specification? */
+ name = malloc (name_end - name_start + 1);
+ if (name == NULL)
+ return P11_KIT_URI_BAD_ENCODING;
+ memcpy (name, name_start, name_end - name_start);
+ name[name_end - name_start] = '\0';
+
+ value = p11_url_decode (start, end, P11_URL_WHITESPACE, NULL);
+ if (value == NULL) {
+ free (name);
+ return P11_KIT_URI_BAD_ENCODING;
+ }
+
+ if (!p11_dict_set (uri->qattrs, name, value))
+ return 1;
+
+ return 0;
+}
+
/**
* p11_kit_uri_parse:
* @string: The string to parse
@@ -1523,6 +1617,7 @@ p11_kit_uri_parse (const char *string, P11KitUriType uri_type,
uri->module_name = NULL;
free (uri->module_path);
uri->module_path = NULL;
+ p11_dict_clear (uri->qattrs);
/* Parse the path. */
for (;;) {
@@ -1593,12 +1688,12 @@ p11_kit_uri_parse (const char *string, P11KitUriType uri_type,
ret = parse_pin_query (string, epos, epos + 1, spos, uri);
if (ret == 0)
ret = parse_module_query (string, epos, epos + 1, spos, uri);
+ if (ret == 0)
+ ret = parse_vendor_query (string, epos, epos + 1, spos, uri);
if (ret < 0) {
free (allocated);
return ret;
}
- if (ret == 0)
- uri->unrecognized = true;
string = spos;
}
@@ -1624,6 +1719,7 @@ p11_kit_uri_free (P11KitUri *uri)
free (uri->pin_value);
free (uri->module_name);
free (uri->module_path);
+ p11_dict_free (uri->qattrs);
free (uri);
}
diff --git a/p11-kit/uri.h b/p11-kit/uri.h
index e4d3330..0982737 100644
--- a/p11-kit/uri.h
+++ b/p11-kit/uri.h
@@ -163,6 +163,12 @@ const char* p11_kit_uri_get_module_path (P11KitUri *uri);
void p11_kit_uri_set_module_path (P11KitUri *uri,
const char *path);
+const char* p11_kit_uri_get_vendor_query (P11KitUri *uri,
+ const char *name);
+int p11_kit_uri_set_vendor_query (P11KitUri *uri,
+ const char *name,
+ const char *value);
+
void p11_kit_uri_set_unrecognized (P11KitUri *uri,
int unrecognized);