1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* gck-uri.c - the GObject PKCS#11 wrapper library
4 Copyright (C) 2010, Stefan Walter
6 The Gnome Keyring Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The Gnome Keyring Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the Gnome Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
21 Author: Stef Walter <stef@memberwebs.com>
27 #include "gck-private.h"
28 #include "gck-marshal.h"
30 #include <glib/gi18n-lib.h>
32 #include <p11-kit/uri.h>
40 * @short_description: Parsing and building PKCS\#11 URIs.
42 * <ulink href='http://tools.ietf.org/html/draft-pechanec-pkcs11uri-03'>PKCS\#11 URIs</ulink>
43 * are a standard for referring to PKCS\#11 modules, tokens, or objects. What the
44 * PKCS\#11 URI refers to depends on the context in which it is used.
46 * A PKCS\#11 URI can always resolve to more than one object, token or module. A
47 * PKCS\#11 URI that refers to a token, would (when used in a context that expects
48 * objects) refer to all the token on that module.
50 * In most cases the parsing or building of URIs is handled elsewhere in the GCK
51 * library. For example to enumerate objects that match a PKCS\#11 URI use the
52 * gck_modules_enumerate_uri() function.
54 * To parse a PKCS\#11 URI use the gck_uri_parse() function passing in the type of
55 * context in which you're using the URI. To build a URI use the gck_uri_build()
61 * @any_unrecognized: whether any parts of the PKCS\#11 URI were unsupported or unrecognized.
62 * @module_info: information about the PKCS\#11 modules matching the URI.
63 * @token_info: information about the PKCS\#11 tokens matching the URI.
64 * @attributes: information about the PKCS\#11 objects matching the URI.
66 * Information about the contents of a PKCS\#11 URI. Various fields may be %NULL
67 * depending on the context that the URI was parsed for.
69 * Since PKCS\#11 URIs represent a set which results from the intersections of
70 * all of the URI parts, if @any_recognized is set to %TRUE then usually the URI
71 * should be treated as not matching anything.
76 * @GCK_URI_FOR_MODULE: the URI will be used to match modules.
77 * @GCK_URI_FOR_TOKEN: the URI will be used to match tokens.
78 * @GCK_URI_FOR_OBJECT: the URI will be used to match objects.
79 * @GCK_URI_WITH_VERSION: the URI has specific version numbers for module and/or token
80 * @GCK_URI_FOR_ANY: parse all recognized components of the URI.
82 * Which parts of the PKCS\#11 URI will be parsed or formatted. These can be
87 * GCK_URI_FOR_MODULE_WITH_VERSION:
89 * The URI will match specific version of modules. To be used as a GckUriFlags argument.
93 * GCK_URI_FOR_OBJECT_ON_TOKEN:
95 * The URI will match objects on a specific token. To be used as a GckUriFlags argument.
99 * GCK_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE:
101 * The token inserted into a device with a specific module.
106 * @GCK_URI_BAD_SCHEME: invalid URI scheme
107 * @GCK_URI_BAD_ENCODING: bad URI encoding
108 * @GCK_URI_BAD_SYNTAX: bad URI syntax
109 * @GCK_URI_BAD_VERSION: bad URI version component
110 * @GCK_URI_NOT_FOUND: piece of the URI was not found
112 * Various error codes used with PKCS\#11 URIs
118 * Error domain for URI errors.
122 * GCK_URI_BAD_PREFIX:
124 * Use %GCK_URI_BAD_SCHEME instead.
126 * Deprecated: Since 3.2
130 * CKR_GCK_MODULE_PROBLEM:
132 * Use %GCK_ERROR_MODULE_PROBLEM instead.
134 * Deprecated: Since 3.4
137 #define URI_PREFIX "pkcs11:"
138 #define N_URI_PREFIX 7
141 gboolean any_unrecognized;
142 GckModuleInfo *module_info;
143 GckTokenInfo *token_info;
144 GckAttributes *attributes;
148 gck_uri_get_error_quark (void)
150 /* This is deprecated version */
151 return gck_uri_get_error_quark ();
155 gck_uri_error_get_quark (void)
157 static GQuark domain = 0;
158 static volatile gsize quark_inited = 0;
160 if (g_once_init_enter (&quark_inited)) {
161 domain = g_quark_from_static_string ("gck-uri-error");
162 g_once_init_leave (&quark_inited, 1);
171 * Allocate a new GckUriData structure. None of the fields
174 * Returns: (transfer full): a newly allocated GckUriData, free with
175 * gck_uri_data_free()
178 gck_uri_data_new (void)
180 return g_slice_new0 (GckUriData);
185 * @string: the URI to parse.
186 * @flags: the context in which the URI will be used.
187 * @error: a #GError, or %NULL.
189 * Parse a PKCS\#11 URI for use in a given context.
191 * The result will contain the fields that are relevant for
192 * the given context. See #GckUriData for more info.
193 * Other fields will be set to %NULL.
195 * Returns: (transfer full): a newly allocated #GckUriData; which should be
196 * freed with gck_uri_data_free()
199 gck_uri_parse (const gchar *string, GckUriFlags flags, GError **error)
201 GckUriData *uri_data = NULL;
202 CK_ATTRIBUTE_PTR attrs;
207 g_return_val_if_fail (string, FALSE);
208 g_return_val_if_fail (!error || !*error, FALSE);
210 p11_uri = p11_kit_uri_new ();
212 g_error ("failed to allocate P11KitUri");
214 res = p11_kit_uri_parse (string, flags, p11_uri);
215 if (res != P11_KIT_URI_OK) {
216 p11_kit_uri_free (p11_uri);
218 case P11_KIT_URI_NO_MEMORY:
219 g_error ("failed to allocate memory in p11_kit_uri_parse()");
221 case P11_KIT_URI_BAD_ENCODING:
222 g_set_error (error, GCK_URI_ERROR, GCK_URI_BAD_ENCODING,
223 _("The URI has invalid encoding."));
225 case P11_KIT_URI_BAD_SCHEME:
226 g_set_error_literal (error, GCK_URI_ERROR, GCK_URI_BAD_SCHEME,
227 _("The URI does not have the 'pkcs11' scheme."));
229 case P11_KIT_URI_BAD_SYNTAX:
230 g_set_error_literal (error, GCK_URI_ERROR, GCK_URI_BAD_SYNTAX,
231 _("The URI has bad syntax."));
233 case P11_KIT_URI_BAD_VERSION:
234 g_set_error_literal (error, GCK_URI_ERROR, GCK_URI_BAD_SYNTAX,
235 _("The URI has a bad version number."));
237 case P11_KIT_URI_NOT_FOUND:
238 g_assert_not_reached ();
244 /* Convert it to a GckUri */
245 uri_data = gck_uri_data_new ();
246 if (flags & GCK_URI_FOR_MODULE_WITH_VERSION)
247 uri_data->module_info = _gck_module_info_from_pkcs11 (p11_kit_uri_get_module_info (p11_uri));
248 if (flags & GCK_URI_FOR_TOKEN)
249 uri_data->token_info = _gck_token_info_from_pkcs11 (p11_kit_uri_get_token_info (p11_uri));
250 if (flags & GCK_URI_FOR_OBJECT) {
251 attrs = p11_kit_uri_get_attributes (p11_uri, &n_attrs);
252 uri_data->attributes = gck_attributes_new ();
253 for (i = 0; i < n_attrs; ++i)
254 gck_attributes_add (uri_data->attributes, (GckAttribute*)&attrs[i]);
256 uri_data->any_unrecognized = p11_kit_uri_any_unrecognized (p11_uri);
258 p11_kit_uri_free (p11_uri);
264 * @uri_data: the info to build the URI from.
265 * @flags: The context that the URI is for
267 * Build a PKCS\#11 URI. The various parts relevant to the flags
268 * specified will be used to build the URI.
270 * Return value: a newly allocated string containing a PKCS\#11 URI.
273 gck_uri_build (GckUriData *uri_data, GckUriFlags flags)
276 P11KitUri *p11_uri = 0;
281 g_return_val_if_fail (uri_data != NULL, NULL);
283 p11_uri = p11_kit_uri_new ();
285 if ((flags & GCK_URI_FOR_MODULE_WITH_VERSION) && uri_data->module_info)
286 _gck_module_info_to_pkcs11 (uri_data->module_info,
287 p11_kit_uri_get_module_info (p11_uri));
288 if ((flags & GCK_URI_FOR_TOKEN) && uri_data->token_info)
289 _gck_token_info_to_pkcs11 (uri_data->token_info,
290 p11_kit_uri_get_token_info (p11_uri));
291 if ((flags & GCK_URI_FOR_OBJECT) && uri_data->attributes) {
292 for (i = 0; i < gck_attributes_count (uri_data->attributes); ++i) {
293 attr = gck_attributes_at (uri_data->attributes, i);
294 res = p11_kit_uri_set_attribute (p11_uri, (CK_ATTRIBUTE_PTR)attr);
295 if (res == P11_KIT_URI_NO_MEMORY)
296 g_error ("failed to allocate memory in p11_kit_uri_set_attribute()");
297 else if (res != P11_KIT_URI_NOT_FOUND && res != P11_KIT_URI_OK)
298 g_return_val_if_reached (NULL);
302 res = p11_kit_uri_format (p11_uri, flags & GCK_URI_FOR_ANY, &string);
303 if (res == P11_KIT_URI_NO_MEMORY)
304 g_error ("failed to allocate memory in p11_kit_uri_format()");
305 else if (res != P11_KIT_URI_OK)
306 g_return_val_if_reached (NULL);
308 p11_kit_uri_free (p11_uri);
313 gck_uri_data_get_type (void)
315 static volatile gsize initialized = 0;
316 static GType type = 0;
317 if (g_once_init_enter (&initialized)) {
318 type = g_boxed_type_register_static ("GckUriData",
319 (GBoxedCopyFunc)gck_uri_data_copy,
320 (GBoxedFreeFunc)gck_uri_data_free);
321 g_once_init_leave (&initialized, 1);
328 * @uri_data: URI data to copy
332 * Returns: (transfer full): newly allocated copy of the uri data
335 gck_uri_data_copy (GckUriData *uri_data)
339 copy = g_memdup (uri_data, sizeof (GckUriData));
340 copy->attributes = gck_attributes_new ();
341 gck_attributes_add_all (copy->attributes, uri_data->attributes);
342 copy->module_info = gck_module_info_copy (copy->module_info);
343 copy->token_info = gck_token_info_copy (copy->token_info);
349 * @uri_data: URI data to free.
351 * Free a #GckUriData.
354 gck_uri_data_free (GckUriData *uri_data)
357 if (uri_data->attributes)
358 gck_attributes_unref (uri_data->attributes);
359 if (uri_data->module_info)
360 gck_module_info_free (uri_data->module_info);
361 if (uri_data->token_info)
362 gck_token_info_free (uri_data->token_info);
363 g_slice_free (GckUriData, uri_data);