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