diff options
author | Stef Walter <stefw@collabora.co.uk> | 2011-05-27 14:42:35 +0200 |
---|---|---|
committer | Stef Walter <stefw@collabora.co.uk> | 2011-05-27 14:45:44 +0200 |
commit | bdd6188e299405e16179906bc79f9fef2605176a (patch) | |
tree | 6d1654e4ee6c4411f1a8075c89353e5ee25c46d2 /p11-kit/p11-kit-uri.c | |
parent | 92f821b6883e700a97a18d244104dea1031f2dce (diff) |
Change around installation of headers, pkg-config, and file names
* Install headers to ${prefix}/include/p11-kit-1/p11-kit/
* This solves problems with other projects that have their own
pkcs11.h files.
* Change the pkg-config file name to p11-kit-1.pc
* Change the source file names.
Diffstat (limited to 'p11-kit/p11-kit-uri.c')
-rw-r--r-- | p11-kit/p11-kit-uri.c | 1337 |
1 files changed, 0 insertions, 1337 deletions
diff --git a/p11-kit/p11-kit-uri.c b/p11-kit/p11-kit-uri.c deleted file mode 100644 index f2ac3ad..0000000 --- a/p11-kit/p11-kit-uri.c +++ /dev/null @@ -1,1337 +0,0 @@ -/* - * 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_URI -#include "debug.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> - -/** - * SECTION:p11-kit-uri - * @title: URIs - * @short_description: Parsing and formatting PKCS\#11 URIs - * - * 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_IS_MODULE: The URI represents one or more modules - * @P11_KIT_URI_IS_TOKEN: The URI represents one or more tokens - * @P11_KIT_URI_IS_OBJECT: The URI represents one or more objects - * @P11_KIT_URI_IS_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. - */ - -/** - * 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. - */ - -static const CK_ATTRIBUTE_TYPE SUPPORTED_ATTRIBUTE_TYPES[] = { - CKA_CLASS, - CKA_LABEL, - CKA_ID -}; - -#define NUM_ATTRIBUTE_TYPES \ - (sizeof (SUPPORTED_ATTRIBUTE_TYPES) / sizeof (SUPPORTED_ATTRIBUTE_TYPES[0])) - -struct _P11KitUri { - int unrecognized; - CK_INFO module; - CK_TOKEN_INFO token; - CK_ATTRIBUTE attributes[NUM_ATTRIBUTE_TYPES]; - CK_ULONG n_attributes; - char *pinfile; -}; - -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++); - } - } - - /* Null terminate string, in case its a string */ - *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 (*value && (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 -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)); -} - -/** - * p11_kit_uri_get_module_info: - * @uri: the URI - * - * Get the <code>CK_INFO</code> structure associated with this URI. - * - * If this is a parsed URI, then the fields corresponding to library parts of - * the URI will be filled in. Any library URI parts that were missing will have - * their fields filled with zeros. - * - * If the caller wishes to setup information for building a URI, then relevant - * fields should be filled in. Fields that should not appear as parts in the - * resulting URI should be filled with zeros. - * - * Returns: A pointer to the <code>CK_INFO</code> structure. - */ -CK_INFO_PTR -p11_kit_uri_get_module_info (P11KitUri *uri) -{ - assert (uri); - return &uri->module; -} - -/** - * p11_kit_uri_match_module_info: - * @uri: the URI - * @info: the structure to match against the URI - * - * Match a <code>CK_INFO</code> structure against the library parts of this URI. - * - * Only the fields of the <code>CK_INFO</code> structure that are valid for use - * in a URI will be matched. A URI part that was not specified in the URI will - * match any value in the structure. If during the URI parsing any unrecognized - * parts were encountered then this match will fail. - * - * Returns: 1 if the URI matches, 0 if not. - */ -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)); -} - -/** - * p11_kit_uri_get_token_info: - * @uri: the URI - * - * Get the <code>CK_TOKEN_INFO</code> structure associated with this URI. - * - * If this is a parsed URI, then the fields corresponding to token parts of - * the URI will be filled in. Any token URI parts that were missing will have - * their fields filled with zeros. - * - * If the caller wishes to setup information for building a URI, then relevant - * fields should be filled in. Fields that should not appear as parts in the - * resulting URI should be filled with zeros. - * - * Returns: A pointer to the <code>CK_INFO</code> structure. - */ -CK_TOKEN_INFO_PTR -p11_kit_uri_get_token_info (P11KitUri *uri) -{ - assert (uri); - return &uri->token; -} - -/** - * p11_kit_uri_match_token_info: - * @uri: the URI - * @token_info: the structure to match against the URI - * - * Match a <code>CK_TOKEN_INFO</code> structure against the token parts of this - * URI. - * - * Only the fields of the <code>CK_TOKEN_INFO</code> structure that are valid - * for use in a URI will be matched. A URI part that was not specified in the - * URI will match any value in the structure. If during the URI parsing any - * unrecognized parts were encountered then this match will fail. - * - * Returns: 1 if the URI matches, 0 if not. - */ -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))); -} - -/** - * p11_kit_uri_get_attribute: - * @uri: The URI - * @attr_type: The attribute type - * - * Get a pointer to an attribute present in this URI. - * - * Returns: A pointer to the attribute, or <code>NULL</code> if not present. - * The attribute is owned by the URI and should not be freed. - */ -CK_ATTRIBUTE_PTR -p11_kit_uri_get_attribute (P11KitUri *uri, CK_ATTRIBUTE_TYPE attr_type) -{ - CK_ULONG i; - - assert (uri); - - for (i = 0; i < uri->n_attributes; i++) { - if (uri->attributes[i].type == attr_type) - return &uri->attributes[i]; - } - - return NULL; -} - -static void -uri_take_attribute (P11KitUri *uri, CK_ATTRIBUTE_PTR attr) -{ - CK_ULONG i; - - assert (uri); - assert (attr); - - /* Replace an attribute already set */ - for (i = 0; i < uri->n_attributes; i++) { - if (uri->attributes[i].type == attr->type) { - free (uri->attributes[i].pValue); - memcpy (&uri->attributes[i], attr, sizeof (CK_ATTRIBUTE)); - memset (attr, 0, sizeof (CK_ATTRIBUTE)); - return; - } - } - - /* Add one at the end */ - assert (uri->n_attributes < NUM_ATTRIBUTE_TYPES); - memcpy (&uri->attributes[uri->n_attributes], attr, sizeof (CK_ATTRIBUTE)); - memset (attr, 0, sizeof (CK_ATTRIBUTE)); - uri->n_attributes++; -} - -/** - * p11_kit_uri_set_attribute: - * @uri: The URI - * @attr: The attribute to set - * - * Set an attribute on the URI. - * - * Only attributes that map to parts in a PKCS\#11 URI will be accepted. - * - * Returns: %P11_KIT_URI_OK if the attribute was successfully set. - * %P11_KIT_URI_NOT_FOUND if the attribute was not valid for a URI. - * %P11_KIT_URI_NO_MEMORY if allocation failed. - */ -int -p11_kit_uri_set_attribute (P11KitUri *uri, CK_ATTRIBUTE_PTR attr) -{ - CK_ATTRIBUTE copy; - CK_ULONG i; - - assert (uri); - assert (attr); - - /* Make sure the attribute type is valid */ - for (i = 0; i < NUM_ATTRIBUTE_TYPES; i++) { - if (SUPPORTED_ATTRIBUTE_TYPES[i] == attr->type) - break; - } - if (i == NUM_ATTRIBUTE_TYPES) - return P11_KIT_URI_NOT_FOUND; - - memcpy (©, attr, sizeof (CK_ATTRIBUTE)); - - /* Duplicate the value */ - if (attr->pValue && attr->ulValueLen && attr->ulValueLen != (CK_ULONG)-1) { - copy.pValue = malloc (attr->ulValueLen); - if (!copy.pValue) - return P11_KIT_URI_NO_MEMORY; - memcpy (copy.pValue, attr->pValue, attr->ulValueLen); - } - - uri_take_attribute (uri, ©); - return P11_KIT_URI_OK; -} - -/** - * p11_kit_uri_clear_attribute: - * @uri: The URI - * @attr_type: The type of the attribute to clear - * - * Clear an attribute on the URI. - * - * Only attributes that map to parts in a PKCS\#11 URI will be accepted. - * - * Returns: %P11_KIT_URI_OK if the attribute was successfully cleared. - * %P11_KIT_URI_NOT_FOUND if the attribute was not valid for a URI. - */ -int -p11_kit_uri_clear_attribute (P11KitUri *uri, CK_ATTRIBUTE_TYPE attr_type) -{ - CK_ATTRIBUTE_PTR clear = NULL; - CK_ATTRIBUTE_PTR last; - CK_ULONG i; - - assert (uri); - - /* Make sure the attribute type is valid */ - for (i = 0; i < NUM_ATTRIBUTE_TYPES; i++) { - if (SUPPORTED_ATTRIBUTE_TYPES[i] == attr_type) - break; - } - if (i == NUM_ATTRIBUTE_TYPES) - return P11_KIT_URI_NOT_FOUND; - - /* Cleanup the values in the attribute */ - for (i = 0; i < uri->n_attributes; i++) { - if (uri->attributes[i].type == attr_type) { - clear = &uri->attributes[i]; - free (uri->attributes[i].pValue); - break; - } - } - - /* A valid attribute, but not present */ - if (clear == NULL) - return P11_KIT_URI_OK; - - assert (uri->n_attributes > 0); - uri->n_attributes--; - - /* If not the last attribute, then make last take its place */ - last = &uri->attributes[uri->n_attributes]; - if (clear != last) { - memcpy (clear, last, sizeof (CK_ATTRIBUTE)); - clear = last; - } - - memset (clear, 0, sizeof (CK_ATTRIBUTE)); - return P11_KIT_URI_OK; -} - -/** - * p11_kit_uri_get_attribute_types: - * @uri: The URI - * @n_attrs: A location to store the number of attributes returned. - * - * Get the attributes present in this URI. The attributes and values are - * owned by the URI. If the URI is modified, then the attributes that were - * returned from this function will not remain consistent. - * - * Returns: The attributes for this URI. These are owned by the URI. - */ -CK_ATTRIBUTE_PTR -p11_kit_uri_get_attributes (P11KitUri *uri, CK_ULONG_PTR n_attrs) -{ - assert (uri); - assert (n_attrs); - - *n_attrs = uri->n_attributes; - return uri->attributes; -} - -int -p11_kit_uri_set_attributes (P11KitUri *uri, CK_ATTRIBUTE_PTR attrs, - CK_ULONG n_attrs) -{ - CK_ULONG i; - int ret; - - assert (uri); - - p11_kit_uri_clear_attributes (uri); - - for (i = 0; i < n_attrs; i++) { - ret = p11_kit_uri_set_attribute (uri, &attrs[i]); - if (ret != P11_KIT_URI_OK && ret != P11_KIT_URI_NOT_FOUND) - return ret; - } - - return P11_KIT_URI_OK; -} - -void -p11_kit_uri_clear_attributes (P11KitUri *uri) -{ - CK_ULONG i; - - assert (uri); - - for (i = 0; i < uri->n_attributes; i++) - free (uri->attributes[i].pValue); - uri->n_attributes = 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; -} - -/** - * p11_kit_uri_match_attributes: - * @uri: The URI - * @attrs: The attributes to match - * @n_attrs: The number of attributes - * - * Match a attributes against the object parts of this URI. - * - * Only the attributes that are valid for use in a URI will be matched. A URI - * part that was not specified in the URI will match any attribute value. If - * during the URI parsing any unrecognized parts were encountered then this - * match will fail. - * - * Returns: 1 if the URI matches, 0 if not. - */ -int -p11_kit_uri_match_attributes (P11KitUri *uri, CK_ATTRIBUTE_PTR attrs, - CK_ULONG n_attrs) -{ - CK_ULONG j; - CK_ULONG i; - - assert (uri); - assert (attrs || !n_attrs); - - if (uri->unrecognized) - return 0; - - for (i = 0; i < uri->n_attributes; i++) { - for (j = 0; j < n_attrs; ++j) { - if (uri->attributes[i].type == attrs[j].type) { - if (!match_attributes (&uri->attributes[i], &attrs[j])) - return 0; - break; - } - } - } - - return 1; -} - -/** - * p11_kit_uri_set_unrecognized: - * @uri: The URI - * @unrecognized: The new unregognized flag value - * - * Set the unrecognized flag on this URI. - * - * The unrecognized flag is automatically set to 1 when during parsing any part - * of the URI is unrecognized. If the unrecognized flag is set to 1, then - * matching against this URI will always fail. - */ -void -p11_kit_uri_set_unrecognized (P11KitUri *uri, int unrecognized) -{ - assert (uri); - uri->unrecognized = unrecognized; -} - -/** - * p11_kit_uri_any_unrecognized: - * @uri: The URI - * - * Get the unrecognized flag for this URI. - * - * The unrecognized flag is automatically set to 1 when during parsing any part - * of the URI is unrecognized. If the unrecognized flag is set to 1, then - * matching against this URI will always fail. - * - * Returns: 1 if unrecognized flag is set, 0 otherwise. - */ -int -p11_kit_uri_any_unrecognized (P11KitUri *uri) -{ - assert (uri); - return uri->unrecognized; -} - -/** - * p11_kit_uri_get_pinfile: - * @uri: The URI - * - * Get the 'pinfile' part of the URI. This is used by some applications to - * lookup a PIN for logging into a PKCS\#11 token. - * - * Returns: The pinfile or %NULL if not present. - */ -const char* -p11_kit_uri_get_pinfile (P11KitUri *uri) -{ - assert (uri); - return uri->pinfile; -} - -/** - * p11_kit_uri_set_pinfile: - * @uri: The URI - * @pinfile: The new pinfile - * - * Set the 'pinfile' part of the URI. This is used by some applications to - * lookup a PIN for logging into a PKCS\#11 token. - */ -void -p11_kit_uri_set_pinfile (P11KitUri *uri, const char *pinfile) -{ - assert (uri); - free (uri->pinfile); - uri->pinfile = strdup (pinfile); -} - -/** - * p11_kit_uri_new: - * - * Create a new blank PKCS\#11 URI. - * - * The new URI is in the right state to parse a string into. All relevant fields - * are zeroed out. Formatting this URI will produce a valid but empty URI. - * - * Returns: A newly allocated URI. This should be freed with p11_kit_uri_free(). - */ -P11KitUri* -p11_kit_uri_new (void) -{ - P11KitUri *uri; - - 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; - - 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_encode_string (char **string, size_t *length, int *is_first, - const char *name, const unsigned char *value, - size_t n_value) -{ - char *encoded; - int ret; - - encoded = url_encode (value, value + n_value, NULL); - if (!encoded) - return 0; - - ret = format_raw_string (string, length, is_first, name, encoded); - free (encoded); - return ret; -} - - -static int -format_struct_string (char **string, size_t *length, int *is_first, - const char *name, const unsigned char *value, - size_t value_max) -{ - size_t len; - - /* Not set */ - if (!value[0]) - return 1; - - len = space_strlen (value, value_max); - return format_encode_string (string, length, is_first, name, value, len); -} - -static int -format_attribute_string (char **string, size_t *length, int *is_first, - const char *name, CK_ATTRIBUTE_PTR attr) -{ - /* Not set */; - if (attr == NULL) - return 1; - - return format_encode_string (string, length, is_first, name, - attr->pValue, attr->ulValueLen); -} - -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 == NULL) - 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; - default: - return 1; - } - - 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); -} - -/** - * p11_kit_uri_format: - * @uri: The URI. - * @uri_type: The type of URI that should be produced. - * @string: Location to store a newly allocated string. - * - * Format a PKCS\#11 URI into a string. - * - * Fields which are zeroed out will not be included in the resulting string. - * Attributes which are not present will also not be included. - * - * The uri_type of URI specified limits the different parts of the resulting - * URI. To format a URI containing all possible information use - * %P11_KIT_URI_IS_ANY - * - * The resulting string should be freed with free(). - * - * Returns: %P11_KIT_URI_OK if the URI was formatted successfully. - * %P11_KIT_URI_NO_MEMORY if memory allocation failed. - */ -int -p11_kit_uri_format (P11KitUri *uri, P11KitUriType uri_type, 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_SCHEME_LEN; - memcpy (result, P11_KIT_URI_SCHEME, length); - result[length] = 0; - - if (uri_type & P11_KIT_URI_IS_MODULE) { - if (!format_struct_string (&result, &length, &is_first, "library-description", - uri->module.libraryDescription, - sizeof (uri->module.libraryDescription)) || - !format_struct_version (&result, &length, &is_first, "library-version", - &uri->module.libraryVersion) || - !format_struct_string (&result, &length, &is_first, "library-manufacturer", - uri->module.manufacturerID, - sizeof (uri->module.manufacturerID))) { - free (result); - return P11_KIT_URI_NO_MEMORY; - } - } - - if (uri_type & P11_KIT_URI_IS_TOKEN) { - if (!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))) { - free (result); - return P11_KIT_URI_NO_MEMORY; - } - } - - if (uri_type & P11_KIT_URI_IS_OBJECT) { - if (!format_attribute_string (&result, &length, &is_first, "id", - p11_kit_uri_get_attribute (uri, CKA_ID)) || - !format_attribute_string (&result, &length, &is_first, "object", - p11_kit_uri_get_attribute (uri, CKA_LABEL))) { - free (result); - return P11_KIT_URI_NO_MEMORY; - } - - if (!format_attribute_class (&result, &length, &is_first, "objecttype", - p11_kit_uri_get_attribute (uri, CKA_CLASS))) { - free (result); - return P11_KIT_URI_NO_MEMORY; - } - } - - if (uri->pinfile) { - format_encode_string (&result, &length, &is_first, "pinfile", - (const unsigned char*)uri->pinfile, - strlen (uri->pinfile)); - } - - *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; - CK_ATTRIBUTE attr; - size_t length; - int ret; - - assert (start <= end); - - if (strcmp ("id", name) == 0) - attr.type = CKA_ID; - else if (strcmp ("object", name) == 0) - attr.type = CKA_LABEL; - else - return 0; - - ret = url_decode (start, end, &value, &length); - if (ret < 0) - return ret; - - attr.pValue = value; - attr.ulValueLen = length; - uri_take_attribute (uri, &attr); - 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; - CK_ATTRIBUTE attr; - - 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; - } - - attr.pValue = malloc (sizeof (klass)); - if (attr.pValue == NULL) - return P11_KIT_URI_NO_MEMORY; - - memcpy (attr.pValue, &klass, sizeof (klass)); - attr.ulValueLen = sizeof (klass); - attr.type = CKA_CLASS; - - uri_take_attribute (uri, &attr); - 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); -} - -static int -parse_extra_info (const char *name, const char *start, const char *end, - P11KitUri *uri) -{ - unsigned char *pinfile; - int ret; - - assert (start <= end); - - if (strcmp (name, "pinfile") == 0) { - ret = url_decode (start, end, &pinfile, NULL); - if (ret < 0) - return ret; - free (uri->pinfile); - uri->pinfile = (char*)pinfile; - return 1; - } - - return 0; -} - -/** - * p11_kit_uri_parse: - * @string: The string to parse - * @uri_type: The type of URI that is expected - * @uri: The blank URI to parse the values into - * - * Parse a PKCS\#11 URI string. - * - * PKCS\#11 URIs can represent tokens, objects or modules. The uri_type argument - * allows the caller to specify what type of URI is expected and the sorts of - * objects the URI should match. %P11_KIT_URI_IS_ANY can be used to parse a URI - * for any context. It's then up to the caller to make sense of the way that - * it is used. - * - * If the PKCS\#11 URI contains unrecognized URI parts or parts not applicable - * to the specified context, then the unrecognized flag will be set. This will - * prevent the URI from matching using the various match functions. - * - * Returns: %P11_KIT_URI_OK if the URI was parsed successfully. - * %P11_KIT_URI_BAD_SCHEME if this was not a PKCS\#11 URI. - * %P11_KIT_URI_BAD_SYNTAX if the URI syntax was bad. - * %P11_KIT_URI_NO_MEMORY if memory allocation failed. - * %P11_KIT_URI_BAD_VERSION if a version number was bad. - * %P11_KIT_URI_BAD_ENCODING if the URI encoding was invalid. - */ -int -p11_kit_uri_parse (const char *string, P11KitUriType uri_type, - P11KitUri *uri) -{ - const char *spos, *epos; - char *key = NULL; - int ret = -1; - int i; - - assert (string); - assert (uri); - - if (strncmp (string, P11_KIT_URI_SCHEME, P11_KIT_URI_SCHEME_LEN) != 0) - return P11_KIT_URI_BAD_SCHEME; - - string += P11_KIT_URI_SCHEME_LEN; - - /* Clear everything out */ - memset (&uri->module, 0, sizeof (uri->module)); - memset (&uri->token, 0, sizeof (uri->module)); - for (i = 0; i < uri->n_attributes; ++i) { - free (uri->attributes[i].pValue); - memset (&uri->attributes[i], 0, sizeof (CK_ATTRIBUTE)); - } - uri->n_attributes = 0; - uri->module.libraryVersion.major = (CK_BYTE)-1; - uri->module.libraryVersion.minor = (CK_BYTE)-1; - uri->unrecognized = 0; - free (uri->pinfile); - uri->pinfile = NULL; - - 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 (uri_type & P11_KIT_URI_IS_OBJECT) - ret = parse_string_attribute (key, epos, spos, uri); - if (ret == 0 && uri_type & P11_KIT_URI_IS_OBJECT) - ret = parse_class_attribute (key, epos, spos, uri); - if (ret == 0 && uri_type & P11_KIT_URI_IS_TOKEN) - ret = parse_token_info (key, epos, spos, uri); - if (ret == 0 && uri_type & P11_KIT_URI_IS_MODULE) - ret = parse_module_info (key, epos, spos, uri); - if (ret == 0) - ret = parse_extra_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; -} - -/** - * p11_kit_uri_free: - * @uri: The URI - * - * Free a PKCS\#11 URI. - */ -void -p11_kit_uri_free (P11KitUri *uri) -{ - int i; - - if (!uri) - return; - - for (i = 0; i < uri->n_attributes; ++i) - free (uri->attributes[i].pValue); - - free (uri); -} - -/** - * p11_kit_uri_message: - * @code: The error code - * - * Lookup a message for the uri error code. These codes are the P11_KIT_URI_XXX - * error codes that can be returned from p11_kit_uri_parse() or - * p11_kit_uri_format(). As a special case %NULL, will be returned for - * %P11_KIT_URI_OK. - * - * Returns: The message for the error code. This string is owned by the p11-kit - * library. - */ -const char* -p11_kit_uri_message (int code) -{ - switch (code) { - case P11_KIT_URI_OK: - return NULL; - case P11_KIT_URI_NO_MEMORY: - return "Out of memory"; - case P11_KIT_URI_BAD_SCHEME: - return "URI scheme must be 'pkcs11:'"; - case P11_KIT_URI_BAD_ENCODING: - return "URI encoding invalid or corrupted"; - case P11_KIT_URI_BAD_SYNTAX: - return "URI syntax is invalid"; - case P11_KIT_URI_BAD_VERSION: - return "URI version component is invalid"; - case P11_KIT_URI_NOT_FOUND: - return "The URI component was not found"; - default: - debug ("unknown error code: %d", code); - return "Unknown error"; - } -} |