From 1e80b5858a90497879e1e3faee4c7f76d5cbd6f0 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Mon, 20 Feb 2017 11:01:21 +0100 Subject: 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. --- doc/manual/p11-kit-sections.txt | 2 + p11-kit/test-uri.c | 40 ++++++++++++++++ p11-kit/uri.c | 100 +++++++++++++++++++++++++++++++++++++++- p11-kit/uri.h | 6 +++ 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); -- cgit v1.1