1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* gck-module.c - the GObject PKCS#11 wrapper library
3
4 Copyright (C) 2008, Stefan Walter
5
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.
10
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.
15
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 see <http://www.gnu.org/licenses/>.
19
20 Author: Stef Walter <nielsen@memberwebs.com>
21 */
22
23 #include "config.h"
24
25 #include "gck.h"
26 #include "gck-private.h"
27
28 #include "gck/gck-marshal.h"
29
30 #include <glib/gi18n-lib.h>
31
32 #define P11_KIT_FUTURE_UNSTABLE_API 1
33 #include <p11-kit/p11-kit.h>
34
35 #include <string.h>
36
37 /**
38 * SECTION:gck-module
39 * @title: GckModule
40 * @short_description: A loaded and initialized PKCS\#11 module.
41 *
42 * A GckModule object holds a loaded PKCS\#11 module. A PKCS\#11 module is a shared library.
43 *
44 * You can load and initialize a PKCS\#11 module with the gck_module_initialize() call. If you already
45 * have a loaded and initialized module that you'd like to use with the various gck functions, then
46 * you can use gck_module_new().
47 */
48
49 /**
50 * GckModule:
51 *
52 * Holds a loaded and initialized PKCS\#11 module.
53 */
54
55 /**
56 * GckModuleInfo:
57 * @pkcs11_version_major: The major version of the module.
58 * @pkcs11_version_minor: The minor version of the module.
59 * @manufacturer_id: The module manufacturer.
60 * @flags: The module PKCS#11 flags.
61 * @library_description: The module description.
62 * @library_version_major: The major version of the library.
63 * @library_version_minor: The minor version of the library.
64 *
65 * Holds information about the PKCS#11 module.
66 *
67 * This structure corresponds to CK_MODULE_INFO in the PKCS\#11 standard. The
68 * strings are %NULL terminated for easier use.
69 *
70 * Use gck_module_info_free() to release this structure when done with it.
71 */
72
73 /*
74 * MT safe
75 *
76 * The only thing that can change after object initialization in
77 * a GckModule is the finalized flag, which can be set
78 * to 1 in dispose.
79 */
80
81 enum {
82 PROP_0,
83 PROP_PATH,
84 PROP_FUNCTIONS
85 };
86
87 enum {
88 AUTHENTICATE_SLOT,
89 AUTHENTICATE_OBJECT,
90 LAST_SIGNAL
91 };
92
93 struct _GckModulePrivate {
94 gchar *path;
95 gboolean initialized;
96 CK_FUNCTION_LIST_PTR funcs;
97 CK_C_INITIALIZE_ARGS init_args;
98
99 /* Modified atomically */
100 gint finalized;
101 };
102
103 G_DEFINE_TYPE_WITH_PRIVATE (GckModule, gck_module, G_TYPE_OBJECT);
104
105 static guint signals[LAST_SIGNAL] = { 0 };
106
107 /* ----------------------------------------------------------------------------
108 * OBJECT
109 */
110
111 static gboolean
gck_module_real_authenticate_slot(GckModule * module,GckSlot * self,gchar * label,gchar ** password)112 gck_module_real_authenticate_slot (GckModule *module, GckSlot *self, gchar *label, gchar **password)
113 {
114 return FALSE;
115 }
116
117 static gboolean
gck_module_real_authenticate_object(GckModule * module,GckObject * object,gchar * label,gchar ** password)118 gck_module_real_authenticate_object (GckModule *module, GckObject *object, gchar *label, gchar **password)
119 {
120 return FALSE;
121 }
122
123 static void
gck_module_init(GckModule * self)124 gck_module_init (GckModule *self)
125 {
126 self->pv = gck_module_get_instance_private (self);
127 }
128
129 static void
gck_module_get_property(GObject * obj,guint prop_id,GValue * value,GParamSpec * pspec)130 gck_module_get_property (GObject *obj, guint prop_id, GValue *value,
131 GParamSpec *pspec)
132 {
133 GckModule *self = GCK_MODULE (obj);
134
135 switch (prop_id) {
136 case PROP_PATH:
137 g_value_set_string (value, gck_module_get_path (self));
138 break;
139 case PROP_FUNCTIONS:
140 g_value_set_pointer (value, gck_module_get_functions (self));
141 break;
142 }
143 }
144
145 static void
gck_module_set_property(GObject * obj,guint prop_id,const GValue * value,GParamSpec * pspec)146 gck_module_set_property (GObject *obj, guint prop_id, const GValue *value,
147 GParamSpec *pspec)
148 {
149 GckModule *self = GCK_MODULE (obj);
150
151 /* Only allowed during initialization */
152 switch (prop_id) {
153 case PROP_PATH:
154 g_return_if_fail (!self->pv->path);
155 self->pv->path = g_value_dup_string (value);
156 break;
157 case PROP_FUNCTIONS:
158 g_return_if_fail (!self->pv->funcs);
159 self->pv->funcs = g_value_get_pointer (value);
160 break;
161 }
162 }
163
164 static void
gck_module_dispose(GObject * obj)165 gck_module_dispose (GObject *obj)
166 {
167 GckModule *self = GCK_MODULE (obj);
168 gboolean finalize = FALSE;
169 CK_RV rv;
170
171 if (self->pv->initialized && self->pv->funcs) {
172 if (g_atomic_int_compare_and_exchange (&self->pv->finalized, 0, 1))
173 finalize = TRUE;
174 }
175
176 /* Must be careful when accessing funcs */
177 if (finalize) {
178 rv = p11_kit_module_finalize (self->pv->funcs);
179 if (rv != CKR_OK) {
180 g_warning ("C_Finalize on module '%s' failed: %s",
181 self->pv->path, gck_message_from_rv (rv));
182 }
183 }
184
185 G_OBJECT_CLASS (gck_module_parent_class)->dispose (obj);
186 }
187
188 static void
gck_module_finalize(GObject * obj)189 gck_module_finalize (GObject *obj)
190 {
191 GckModule *self = GCK_MODULE (obj);
192
193 if (self->pv->initialized && self->pv->funcs)
194 p11_kit_module_release (self->pv->funcs);
195 self->pv->funcs = NULL;
196
197 g_free (self->pv->path);
198 self->pv->path = NULL;
199
200 G_OBJECT_CLASS (gck_module_parent_class)->finalize (obj);
201 }
202
203
204 static void
gck_module_class_init(GckModuleClass * klass)205 gck_module_class_init (GckModuleClass *klass)
206 {
207 GObjectClass *gobject_class = (GObjectClass*)klass;
208 gck_module_parent_class = g_type_class_peek_parent (klass);
209
210 gobject_class->get_property = gck_module_get_property;
211 gobject_class->set_property = gck_module_set_property;
212 gobject_class->dispose = gck_module_dispose;
213 gobject_class->finalize = gck_module_finalize;
214
215 klass->authenticate_object = gck_module_real_authenticate_object;
216 klass->authenticate_slot = gck_module_real_authenticate_slot;
217
218 /**
219 * GckModule:path:
220 *
221 * The PKCS#11 module file path.
222 *
223 * This may be set to NULL if this object was created from an already
224 * initialized module via the gck_module_new() function.
225 */
226 g_object_class_install_property (gobject_class, PROP_PATH,
227 g_param_spec_string ("path", "Module Path", "Path to the PKCS11 Module",
228 NULL,
229 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
230
231 /**
232 * GckModule:functions:
233 *
234 * The raw PKCS#11 function list for the module.
235 *
236 * This points to a CK_FUNCTION_LIST structure.
237 */
238 g_object_class_install_property (gobject_class, PROP_FUNCTIONS,
239 g_param_spec_pointer ("functions", "Function List", "PKCS11 Function List",
240 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
241
242 /**
243 * GckModule::authenticate-slot:
244 * @module: The module
245 * @slot: The slot to be authenticated.
246 * @string: A displayable label which describes the object.
247 * @password: A gchar** where a password should be returned.
248 *
249 * Use gck_session_set_interaction() instead of connecting to this signal.
250 *
251 * Deprecated: Since 3.4
252 */
253 signals[AUTHENTICATE_SLOT] = g_signal_new ("authenticate-slot", GCK_TYPE_MODULE,
254 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GckModuleClass, authenticate_slot),
255 g_signal_accumulator_true_handled, NULL, _gck_marshal_BOOLEAN__OBJECT_STRING_POINTER,
256 G_TYPE_BOOLEAN, 3, GCK_TYPE_SLOT, G_TYPE_STRING, G_TYPE_POINTER);
257
258 /**
259 * GckModule::authenticate-object:
260 * @module: The module.
261 * @object: The object to be authenticated.
262 * @label: A displayable label which describes the object.
263 * @password: A gchar** where a password should be returned.
264 *
265 * Use gck_session_set_interaction() instead of connecting to this signal.
266 *
267 * Deprecated: Since 3.4
268 */
269 signals[AUTHENTICATE_OBJECT] = g_signal_new ("authenticate-object", GCK_TYPE_MODULE,
270 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GckModuleClass, authenticate_object),
271 g_signal_accumulator_true_handled, NULL, _gck_marshal_BOOLEAN__OBJECT_STRING_POINTER,
272 G_TYPE_BOOLEAN, 3, GCK_TYPE_OBJECT, G_TYPE_STRING, G_TYPE_POINTER);
273 }
274
G_DEFINE_BOXED_TYPE(GckModuleInfo,gck_module_info,gck_module_info_copy,gck_module_info_free)275 G_DEFINE_BOXED_TYPE (GckModuleInfo, gck_module_info,
276 gck_module_info_copy, gck_module_info_free)
277
278 /**
279 * gck_module_info_copy:
280 * @module_info: a module info
281 *
282 * Make a copy of the module info.
283 *
284 * Returns: (transfer full): a newly allocated copy module info
285 */
286 GckModuleInfo *
287 gck_module_info_copy (GckModuleInfo *module_info)
288 {
289 if (module_info == NULL)
290 return NULL;
291
292 module_info = g_memdup (module_info, sizeof (GckModuleInfo));
293 module_info->manufacturer_id = g_strdup (module_info->manufacturer_id);
294 module_info->library_description = g_strdup (module_info->library_description);
295 return module_info;
296
297 }
298
299 /**
300 * gck_module_info_free:
301 * @module_info: The module info to free, or %NULL.
302 *
303 * Free a GckModuleInfo structure.
304 **/
305 void
gck_module_info_free(GckModuleInfo * module_info)306 gck_module_info_free (GckModuleInfo *module_info)
307 {
308 if (!module_info)
309 return;
310 g_free (module_info->library_description);
311 g_free (module_info->manufacturer_id);
312 g_free (module_info);
313 }
314
315 typedef struct {
316 GckArguments base;
317 gchar *path;
318 GckModule *result;
319 GError *error;
320 } Initialize;
321
322 static CK_RV
perform_initialize(Initialize * args)323 perform_initialize (Initialize *args)
324 {
325 CK_FUNCTION_LIST_PTR funcs;
326 GckModule *result;
327 CK_RV rv;
328
329 funcs = p11_kit_module_load (args->path, P11_KIT_MODULE_CRITICAL);
330 if (funcs == NULL) {
331 g_set_error (&args->error, GCK_ERROR, (int)CKR_GCK_MODULE_PROBLEM,
332 _("Error loading PKCS#11 module: %s"), p11_kit_message ());
333 return CKR_GCK_MODULE_PROBLEM;
334 }
335
336 result = g_object_new (GCK_TYPE_MODULE,
337 "functions", funcs,
338 "path", args->path,
339 NULL);
340
341 /* Now initialize the module */
342 rv = p11_kit_module_initialize (funcs);
343 if (rv != CKR_OK) {
344 p11_kit_module_release (funcs);
345 g_set_error (&args->error, GCK_ERROR, rv,
346 _("Couldn’t initialize PKCS#11 module: %s"),
347 gck_message_from_rv (rv));
348 g_object_unref (result);
349 return rv;
350 }
351
352 result->pv->initialized = TRUE;
353 args->result = result;
354 return CKR_OK;
355 }
356
357 static void
free_initialize(Initialize * args)358 free_initialize (Initialize *args)
359 {
360 g_free (args->path);
361 g_clear_error (&args->error);
362 g_clear_object (&args->result);
363 g_free (args);
364 }
365
366 /**
367 * gck_module_initialize:
368 * @path: The file system path to the PKCS\#11 module to load.
369 * @cancellable: (nullable): optional cancellation object
370 * @error: A location to store an error resulting from a failed load.
371 *
372 * Load and initialize a PKCS\#11 module represented by a GckModule object.
373 *
374 * Return value: (transfer full): The loaded PKCS\#11 module or %NULL if failed.
375 **/
376 GckModule*
gck_module_initialize(const gchar * path,GCancellable * cancellable,GError ** error)377 gck_module_initialize (const gchar *path,
378 GCancellable *cancellable,
379 GError **error)
380 {
381 Initialize args = { GCK_ARGUMENTS_INIT, 0, };
382
383 g_return_val_if_fail (path != NULL, NULL);
384 g_return_val_if_fail (!error || !*error, NULL);
385
386 args.path = g_strdup (path);
387
388 if (!_gck_call_sync (NULL, perform_initialize, NULL, &args, cancellable, error)) {
389
390 /* A custom error from perform_initialize */
391 if (args.error) {
392 g_clear_error (error);
393 g_propagate_error (error, args.error);
394 args.error = NULL;
395 }
396 }
397
398 g_free (args.path);
399 g_clear_error (&args.error);
400 return args.result;
401 }
402
403 /**
404 * gck_module_initialize_async:
405 * @path: the file system path to the PKCS\#11 module to load
406 * @cancellable: (nullable): optional cancellation object
407 * @callback: a callback which will be called when the operation completes
408 * @user_data: data to pass to the callback
409 *
410 * Asynchronously load and initialize a PKCS\#11 module represented by a
411 * #GckModule object.
412 **/
413 void
gck_module_initialize_async(const gchar * path,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)414 gck_module_initialize_async (const gchar *path,
415 GCancellable *cancellable,
416 GAsyncReadyCallback callback,
417 gpointer user_data)
418 {
419 Initialize *args;
420 GckCall *call;
421
422 g_return_if_fail (path != NULL);
423
424 call = _gck_call_async_prep (NULL, perform_initialize, NULL,
425 sizeof (*args), free_initialize);
426 args = _gck_call_get_arguments (call);
427 args->path = g_strdup (path);
428
429 _gck_call_async_ready_go (call, NULL, cancellable, callback, user_data);
430 }
431
432 /**
433 * gck_module_initialize_finish:
434 * @result: the asynchronous result
435 * @error: location to place an error on failure
436 *
437 * Finishes the asynchronous initialize operation.
438 *
439 * Returns: (transfer full) (nullable): The initialized module, or %NULL
440 */
441 GckModule *
gck_module_initialize_finish(GAsyncResult * result,GError ** error)442 gck_module_initialize_finish (GAsyncResult *result,
443 GError **error)
444 {
445 GckModule *module = NULL;
446 Initialize *args;
447
448 args = _gck_call_async_result_arguments (result, Initialize);
449 if (_gck_call_basic_finish (result, error)) {
450 module = args->result;
451 args->result = NULL;
452
453 } else {
454 /* A custom error from perform_initialize */
455 if (args->error) {
456 g_clear_error (error);
457 g_propagate_error (error, args->error);
458 args->error = NULL;
459 }
460 }
461
462 return module;
463 }
464
465 /**
466 * gck_module_new: (skip)
467 * @funcs: Initialized PKCS\#11 function list pointer
468 *
469 * Create a GckModule representing a PKCS\#11 module. It is assumed that
470 * this the module is already initialized. In addition it will not be
471 * finalized when complete.
472 *
473 * Return value: The new PKCS\#11 module.
474 **/
475 GckModule*
gck_module_new(CK_FUNCTION_LIST_PTR funcs)476 gck_module_new (CK_FUNCTION_LIST_PTR funcs)
477 {
478 g_return_val_if_fail (funcs != NULL, NULL);
479 return g_object_new (GCK_TYPE_MODULE, "functions", funcs, NULL);
480 }
481
482 GckModule*
_gck_module_new_initialized(CK_FUNCTION_LIST_PTR funcs)483 _gck_module_new_initialized (CK_FUNCTION_LIST_PTR funcs)
484 {
485 GckModule *module = gck_module_new (funcs);
486 module->pv->initialized = TRUE; /* As if we initialized it */
487 return module;
488 }
489
490 /**
491 * gck_module_equal:
492 * @module1: (type Gck.Module): a pointer to the first #GckModule
493 * @module2: (type Gck.Module): a pointer to the second #GckModule
494 *
495 * Checks equality of two modules. Two GckModule objects can point to the same
496 * underlying PKCS\#11 module.
497 *
498 * Return value: %TRUE if module1 and module2 are equal.
499 * %FALSE if either is not a GckModule.
500 **/
501 gboolean
gck_module_equal(gconstpointer module1,gconstpointer module2)502 gck_module_equal (gconstpointer module1, gconstpointer module2)
503 {
504 GckModule *mod1, *mod2;
505
506 if (module1 == module2)
507 return TRUE;
508 if (!GCK_IS_MODULE (module1) || !GCK_IS_MODULE (module2))
509 return FALSE;
510
511 mod1 = GCK_MODULE (module1);
512 mod2 = GCK_MODULE (module2);
513
514 return mod1->pv->funcs == mod2->pv->funcs;
515 }
516
517 /**
518 * gck_module_hash:
519 * @module: (type Gck.Module): a pointer to a #GckModule
520 *
521 * Create a hash value for the GckModule.
522 *
523 * This function is intended for easily hashing a GckModule to add to
524 * a GHashTable or similar data structure.
525 *
526 * Return value: An integer that can be used as a hash value, or 0 if invalid.
527 **/
528 guint
gck_module_hash(gconstpointer module)529 gck_module_hash (gconstpointer module)
530 {
531 GckModule *self;
532
533 g_return_val_if_fail (GCK_IS_MODULE (module), 0);
534 self = GCK_MODULE (module);
535 return g_direct_hash (self->pv->funcs);
536 }
537
538 GckModuleInfo*
_gck_module_info_from_pkcs11(CK_INFO_PTR info)539 _gck_module_info_from_pkcs11 (CK_INFO_PTR info)
540 {
541 GckModuleInfo *modinfo;
542
543 modinfo = g_new0 (GckModuleInfo, 1);
544 modinfo->flags = info->flags;
545 modinfo->library_description = gck_string_from_chars (info->libraryDescription,
546 sizeof (info->libraryDescription));
547 modinfo->manufacturer_id = gck_string_from_chars (info->manufacturerID,
548 sizeof (info->manufacturerID));
549 modinfo->library_version_major = info->libraryVersion.major;
550 modinfo->library_version_minor = info->libraryVersion.minor;
551 modinfo->pkcs11_version_major = info->cryptokiVersion.major;
552 modinfo->pkcs11_version_minor = info->cryptokiVersion.minor;
553
554 return modinfo;
555 }
556
557 void
_gck_module_info_to_pkcs11(GckModuleInfo * module_info,CK_INFO_PTR info)558 _gck_module_info_to_pkcs11 (GckModuleInfo* module_info, CK_INFO_PTR info)
559 {
560 info->flags = module_info->flags;
561 if (!gck_string_to_chars (info->libraryDescription,
562 sizeof (info->libraryDescription),
563 module_info->library_description))
564 g_return_if_reached ();
565 if (!gck_string_to_chars (info->manufacturerID,
566 sizeof (info->manufacturerID),
567 module_info->manufacturer_id))
568 g_return_if_reached ();
569
570 info->libraryVersion.major = module_info->library_version_major;
571 info->libraryVersion.minor = module_info->library_version_minor;
572 info->cryptokiVersion.major = module_info->pkcs11_version_major;
573 info->cryptokiVersion.minor = module_info->pkcs11_version_minor;
574 }
575
576 /**
577 * gck_module_get_info:
578 * @self: The module to get info for.
579 *
580 * Get the info about a PKCS\#11 module.
581 *
582 * Returns: (transfer full): the module info; release this with gck_module_info_free()
583 **/
584 GckModuleInfo*
gck_module_get_info(GckModule * self)585 gck_module_get_info (GckModule *self)
586 {
587 CK_INFO info;
588 CK_RV rv;
589
590 g_return_val_if_fail (GCK_IS_MODULE (self), NULL);
591 g_return_val_if_fail (self->pv->funcs, NULL);
592
593 memset (&info, 0, sizeof (info));
594 rv = (self->pv->funcs->C_GetInfo (&info));
595 if (rv != CKR_OK) {
596 g_warning ("couldn't get module info: %s", gck_message_from_rv (rv));
597 return NULL;
598 }
599
600 return _gck_module_info_from_pkcs11 (&info);
601 }
602
603 /**
604 * gck_module_get_slots:
605 * @self: The module for which to get the slots.
606 * @token_present: Whether to limit only to slots with a token present.
607 *
608 * Get the GckSlot objects for a given module.
609 *
610 * Return value: (element-type Gck.Slot) (transfer full): The possibly empty
611 * list of slots. Release this with gck_list_unref_free().
612 */
613 GList*
gck_module_get_slots(GckModule * self,gboolean token_present)614 gck_module_get_slots (GckModule *self, gboolean token_present)
615 {
616 CK_SLOT_ID_PTR slot_list;
617 CK_ULONG count, i;
618 GList *result;
619 CK_RV rv;
620
621 g_return_val_if_fail (GCK_IS_MODULE (self), NULL);
622 g_return_val_if_fail (self->pv->funcs, NULL);
623
624 rv = (self->pv->funcs->C_GetSlotList) (token_present ? CK_TRUE : CK_FALSE, NULL, &count);
625 if (rv != CKR_OK) {
626 g_warning ("couldn't get slot count: %s", gck_message_from_rv (rv));
627 return NULL;
628 }
629
630 if (!count)
631 return NULL;
632
633 slot_list = g_new (CK_SLOT_ID, count);
634 rv = (self->pv->funcs->C_GetSlotList) (token_present ? CK_TRUE : CK_FALSE, slot_list, &count);
635 if (rv != CKR_OK) {
636 g_warning ("couldn't get slot list: %s", gck_message_from_rv (rv));
637 g_free (slot_list);
638 return NULL;
639 }
640
641 result = NULL;
642 for (i = 0; i < count; ++i) {
643 result = g_list_prepend (result, g_object_new (GCK_TYPE_SLOT,
644 "handle", slot_list[i],
645 "module", self, NULL));
646 }
647
648 g_free (slot_list);
649 return g_list_reverse (result);
650 }
651
652 /**
653 * gck_module_get_path:
654 * @self: The module for which to get the path.
655 *
656 * Get the file path of this module. This may not be an absolute path, and
657 * usually reflects the path passed to gck_module_initialize().
658 *
659 * Return value: The path, do not modify or free this value.
660 **/
661 const gchar*
gck_module_get_path(GckModule * self)662 gck_module_get_path (GckModule *self)
663 {
664 g_return_val_if_fail (GCK_IS_MODULE (self), NULL);
665 return self->pv->path;
666 }
667
668 /**
669 * gck_module_get_functions: (skip)
670 * @self: The module for which to get the function list.
671 *
672 * Get the PKCS\#11 function list for the module.
673 *
674 * Return value: The function list, do not modify this structure.
675 **/
676 CK_FUNCTION_LIST_PTR
gck_module_get_functions(GckModule * self)677 gck_module_get_functions (GckModule *self)
678 {
679 g_return_val_if_fail (GCK_IS_MODULE (self), NULL);
680 return self->pv->funcs;
681 }
682
683 /**
684 * gck_module_match:
685 * @self: the module to match
686 * @uri: the uri to match against the module
687 *
688 * Check whether the PKCS\#11 URI matches the module
689 *
690 * Returns: whether the URI matches or not
691 */
692 gboolean
gck_module_match(GckModule * self,GckUriData * uri)693 gck_module_match (GckModule *self,
694 GckUriData *uri)
695 {
696 gboolean match = TRUE;
697 GckModuleInfo *info;
698
699 g_return_val_if_fail (GCK_IS_MODULE (self), FALSE);
700 g_return_val_if_fail (uri != NULL, FALSE);
701
702 if (uri->any_unrecognized)
703 match = FALSE;
704
705 if (match && uri->module_info) {
706 info = gck_module_get_info (self);
707 match = _gck_module_info_match (uri->module_info, info);
708 gck_module_info_free (info);
709 }
710
711 return match;
712 }
713