/** * gck_module_equal: * @module1: A pointer to the first GckModule * @module2: A pointer to the second GckModule * * Checks equality of two modules. Two GckModule objects can point to the same * underlying PKCS#11 module. * * Return value: TRUE if module1 and module2 are equal. FALSE if either is not a GckModule. **/ gboolean gck_module_equal (gconstpointer module1, gconstpointer module2) { GckModule *mod1, *mod2; if (module1 == module2) return TRUE; if (!GCK_IS_MODULE (module1) || !GCK_IS_MODULE (module2)) return FALSE; mod1 = GCK_MODULE (module1); mod2 = GCK_MODULE (module2); return mod1->pv->funcs == mod2->pv->funcs; }
gboolean _gck_module_fire_authenticate_slot (GckModule *self, GckSlot *slot, gchar *label, gchar **password) { GckTokenInfo *info; gchar *allocated = NULL; gboolean ret; g_assert (GCK_IS_MODULE (self)); info = gck_slot_get_token_info (slot); if (info != NULL) { /* * We'll have tried to login at least once at this point, * with NULL password. This means that CKF_PROTECTED_AUTHENTICATION_PATH * tokens have had their chance and we don't need to prompt for it. */ if (info->flags & CKF_PROTECTED_AUTHENTICATION_PATH) return FALSE; if (label == NULL) label = allocated = g_strdup (info->label); gck_token_info_free (info); } g_signal_emit (self, signals[AUTHENTICATE_SLOT], 0, slot, label, password, &ret); g_free (allocated); return ret; }
gboolean _gck_module_fire_authenticate_object (GckModule *self, GckObject *object, gchar *label, gchar **password) { GckTokenInfo *info; GckSession *session; GckSlot *slot; gboolean ret; g_assert (GCK_IS_MODULE (self)); g_assert (GCK_IS_OBJECT (object)); g_assert (password); session = gck_object_get_session (object); slot = gck_session_get_slot (session); g_object_unref (session); info = gck_slot_get_token_info (slot); g_object_unref (slot); if (info != NULL) { if (info->flags & CKF_PROTECTED_AUTHENTICATION_PATH) { gck_token_info_free (info); *password = NULL; return TRUE; } gck_token_info_free (info); } g_signal_emit (self, signals[AUTHENTICATE_OBJECT], 0, object, label, password, &ret); return ret; }
/** * gck_slot_has_flags: * @self: The GckSlot object. * @flags: The flags to check. * * Check if the PKCS11 slot has the given flags. * * Returns: Whether one or more flags exist. */ gboolean gck_slot_has_flags (GckSlot *self, gulong flags) { CK_FUNCTION_LIST_PTR funcs; GckModule *module = NULL; CK_TOKEN_INFO info; CK_SLOT_ID handle; CK_RV rv; g_return_val_if_fail (GCK_IS_SLOT (self), FALSE); g_object_get (self, "module", &module, "handle", &handle, NULL); g_return_val_if_fail (GCK_IS_MODULE (module), FALSE); funcs = gck_module_get_functions (module); g_return_val_if_fail (funcs, FALSE); memset (&info, 0, sizeof (info)); rv = (funcs->C_GetTokenInfo) (handle, &info); g_object_unref (module); if (rv != CKR_OK) { g_warning ("couldn't get slot info: %s", gck_message_from_rv (rv)); return FALSE; } return (info.flags & flags) != 0; }
/** * gck_module_get_info: * @self: The module to get info for. * * Get the info about a PKCS#11 module. * * Return value: The module info. Release this with gck_module_info_free(). **/ GckModuleInfo* gck_module_get_info (GckModule *self) { GckModuleInfo *modinfo; CK_INFO info; CK_RV rv; g_return_val_if_fail (GCK_IS_MODULE (self), NULL); g_return_val_if_fail (self->pv->funcs, NULL); memset (&info, 0, sizeof (info)); rv = (self->pv->funcs->C_GetInfo (&info)); if (rv != CKR_OK) { g_warning ("couldn't get module info: %s", gck_message_from_rv (rv)); return NULL; } modinfo = g_new0 (GckModuleInfo, 1); modinfo->flags = info.flags; modinfo->library_description = gck_string_from_chars (info.libraryDescription, sizeof (info.libraryDescription)); modinfo->manufacturer_id = gck_string_from_chars (info.manufacturerID, sizeof (info.manufacturerID)); modinfo->library_version_major = info.libraryVersion.major; modinfo->library_version_minor = info.libraryVersion.minor; modinfo->pkcs11_version_major = info.cryptokiVersion.major; modinfo->pkcs11_version_minor = info.cryptokiVersion.minor; return modinfo; }
/** * gck_slot_get_module: * @self: The slot to get the module for. * * Get the module that this slot is on. * * Return value: The module, you must unreference this after you're done with it. */ GckModule* gck_slot_get_module (GckSlot *self) { g_return_val_if_fail (GCK_IS_SLOT (self), NULL); g_return_val_if_fail (GCK_IS_MODULE (self->pv->module), NULL); return g_object_ref (self->pv->module); }
static gpointer run_client_thread (gpointer data) { gint *socket = data; GError *error = NULL; GkdGpgAgentCall call; GIOStatus status; gboolean cont = TRUE; gchar *line; gsize n_line; g_assert (GCK_IS_MODULE (pkcs11_module)); call.sock = g_atomic_int_get (socket); call.channel = g_io_channel_unix_new (call.sock); g_io_channel_set_encoding (call.channel, NULL, NULL); g_io_channel_set_close_on_unref (call.channel, FALSE); call.module = g_object_ref (pkcs11_module); /* Initial response on the connection */ gkd_gpg_agent_send_reply (&call, TRUE, "your orders please"); while (cont) { line = NULL; n_line = 0; /* Read in a line */ status = g_io_channel_read_line (call.channel, &line, &n_line, NULL, &error); switch (status) { case G_IO_STATUS_ERROR: g_critical ("gpg agent couldn't read from socket: %s", egg_error_message (error)); g_clear_error (&error); cont = FALSE; break; case G_IO_STATUS_NORMAL: cont = process_line (&call, line); g_free (line); break; case G_IO_STATUS_EOF: cont = FALSE; break; case G_IO_STATUS_AGAIN: break; default: g_return_val_if_reached (NULL); break; }; } g_io_channel_shutdown (call.channel, FALSE, NULL); g_object_unref (call.module); close (call.sock); g_atomic_int_set (socket, -1); return NULL; }
/** * gck_module_hash: * @module: A pointer to a GckModule * * Create a hash value for the GckModule. * * This function is intended for easily hashing a GckModule to add to * a GHashTable or similar data structure. * * Return value: An integer that can be used as a hash value, or 0 if invalid. **/ guint gck_module_hash (gconstpointer module) { GckModule *self; g_return_val_if_fail (GCK_IS_MODULE (module), 0); self = GCK_MODULE (module); return g_direct_hash (self->pv->funcs); }
gboolean gkd_ssh_agent_initialize_with_module (GckModule *module) { GckSession *session = NULL; GList *slots, *l; GArray *mechs; GError *error = NULL; g_assert (GCK_IS_MODULE (module)); /* Find a good slot for our session keys */ slots = gck_module_get_slots (module, TRUE); for (l = slots; session == NULL && l; l = g_list_next (l)) { /* Check that it has the mechanisms we need */ mechs = gck_slot_get_mechanisms (l->data); if (gck_mechanisms_check (mechs, CKM_RSA_PKCS, CKM_DSA, GCK_INVALID)) { /* Try and open a session */ session = gck_slot_open_session (l->data, GCK_SESSION_AUTHENTICATE, NULL, &error); if (!session) { g_warning ("couldn't create pkcs#11 session: %s", egg_error_message (error)); g_clear_error (&error); } } g_array_unref (mechs); } gck_list_unref_free (slots); if (!session) { g_warning ("couldn't select a usable pkcs#11 slot for the ssh agent to use"); return FALSE; } g_assert (!pkcs11_modules); pkcs11_modules = g_list_append (NULL, g_object_ref (module)); pkcs11_main_mutex = g_new0 (GMutex, 1); g_mutex_init (pkcs11_main_mutex); pkcs11_main_cond = g_new0 (GCond, 1); g_cond_init (pkcs11_main_cond); pkcs11_main_checked = FALSE; pkcs11_main_session = session; return TRUE; }
void _gck_call_async_object (GckCall *call, gpointer object) { g_assert (GCK_IS_CALL (call)); g_assert (call->args); if (call->module) g_object_unref (call->module); call->module = NULL; g_object_get (object, "module", &call->module, "handle", &call->args->handle, NULL); g_assert (GCK_IS_MODULE (call->module)); call->args->pkcs11 = gck_module_get_functions (call->module); /* We now hold a reference on module until finalize */ }
/** * gck_slot_get_mechanisms: * @self: The slot to get mechanisms for. * * Get the available mechanisms for this slot. * * Return value: A list of the mechanisms for this slot. Use * gck_mechanisms_free() when done with this. **/ GckMechanisms* gck_slot_get_mechanisms (GckSlot *self) { CK_SLOT_ID handle = (CK_SLOT_ID)-1; CK_FUNCTION_LIST_PTR funcs; GckModule *module = NULL; CK_MECHANISM_TYPE_PTR mech_list = NULL; CK_ULONG count, i; GckMechanisms *result; CK_RV rv; g_return_val_if_fail (GCK_IS_SLOT (self), NULL); g_object_get (self, "module", &module, "handle", &handle, NULL); g_return_val_if_fail (GCK_IS_MODULE (module), NULL); funcs = gck_module_get_functions (module); g_return_val_if_fail (funcs, NULL); rv = (funcs->C_GetMechanismList) (handle, NULL, &count); if (rv != CKR_OK) { g_warning ("couldn't get mechanism count: %s", gck_message_from_rv (rv)); count = 0; } else { mech_list = g_new (CK_MECHANISM_TYPE, count); rv = (funcs->C_GetMechanismList) (handle, mech_list, &count); if (rv != CKR_OK) { g_warning ("couldn't get mechanism list: %s", gck_message_from_rv (rv)); g_free (mech_list); count = 0; } } g_object_unref (module); if (!count) return NULL; result = g_array_new (FALSE, TRUE, sizeof (CK_MECHANISM_TYPE)); for (i = 0; i < count; ++i) g_array_append_val (result, mech_list[i]); g_free (mech_list); return result; }
/** * gck_module_get_info: * @self: The module to get info for. * * Get the info about a PKCS\#11 module. * * Returns: (transfer full): the module info; release this with gck_module_info_free() **/ GckModuleInfo* gck_module_get_info (GckModule *self) { CK_INFO info; CK_RV rv; g_return_val_if_fail (GCK_IS_MODULE (self), NULL); g_return_val_if_fail (self->pv->funcs, NULL); memset (&info, 0, sizeof (info)); rv = (self->pv->funcs->C_GetInfo (&info)); if (rv != CKR_OK) { g_warning ("couldn't get module info: %s", gck_message_from_rv (rv)); return NULL; } return _gck_module_info_from_pkcs11 (&info); }
gboolean gkd_gpg_agent_initialize_with_module (GckModule *module) { GckSession *session = NULL; GckSlot *slot; GError *error = NULL; GList *modules; g_assert (GCK_IS_MODULE (module)); /* * Find the right slot. */ modules = g_list_append (NULL, module); slot = gck_modules_token_for_uri (modules, "pkcs11:token=Secret%20Store", &error); g_list_free (modules); if (!slot) { g_warning ("couldn't find secret store module: %s", egg_error_message (error)); g_clear_error (&error); return FALSE; } /* Try and open a session */ session = gck_slot_open_session (slot, GCK_SESSION_READ_WRITE | GCK_SESSION_AUTHENTICATE, NULL, &error); g_object_unref (slot); if (!session) { g_warning ("couldn't select a usable pkcs#11 slot for the gpg agent to use"); g_clear_error (&error); return FALSE; } pkcs11_module = g_object_ref (module); pkcs11_main_mutex = g_mutex_new (); pkcs11_main_cond = g_cond_new (); pkcs11_main_checked = FALSE; pkcs11_main_session = session; cache_settings = g_settings_new ("org.mate.crypto.cache"); return TRUE; }
/** * gck_slot_get_info: * @self: The slot to get info for. * * Get the information for this slot. * * Return value: The slot information. When done, use gck_slot_info_free() * to release it. **/ GckSlotInfo* gck_slot_get_info (GckSlot *self) { CK_SLOT_ID handle = (CK_SLOT_ID)-1; GckModule *module = NULL; CK_FUNCTION_LIST_PTR funcs; GckSlotInfo *slotinfo; CK_SLOT_INFO info; CK_RV rv; g_return_val_if_fail (GCK_IS_SLOT (self), NULL); g_object_get (self, "module", &module, "handle", &handle, NULL); g_return_val_if_fail (GCK_IS_MODULE (module), NULL); funcs = gck_module_get_functions (module); g_return_val_if_fail (funcs, NULL); memset (&info, 0, sizeof (info)); rv = (funcs->C_GetSlotInfo) (handle, &info); g_object_unref (module); if (rv != CKR_OK) { g_warning ("couldn't get slot info: %s", gck_message_from_rv (rv)); return NULL; } slotinfo = g_new0 (GckSlotInfo, 1); slotinfo->slot_description = gck_string_from_chars (info.slotDescription, sizeof (info.slotDescription)); slotinfo->manufacturer_id = gck_string_from_chars (info.manufacturerID, sizeof (info.manufacturerID)); slotinfo->flags = info.flags; slotinfo->hardware_version_major = info.hardwareVersion.major; slotinfo->hardware_version_minor = info.hardwareVersion.minor; slotinfo->firmware_version_major = info.firmwareVersion.major; slotinfo->firmware_version_minor = info.firmwareVersion.minor; return slotinfo; }
/** * gck_module_match: * @self: the module to match * @uri: the uri to match against the module * * Check whether the PKCS\#11 URI matches the module * * Returns: whether the URI matches or not */ gboolean gck_module_match (GckModule *self, GckUriData *uri) { gboolean match = TRUE; GckModuleInfo *info; g_return_val_if_fail (GCK_IS_MODULE (self), FALSE); g_return_val_if_fail (uri != NULL, FALSE); if (uri->any_unrecognized) match = FALSE; if (match && uri->module_info) { info = gck_module_get_info (self); match = _gck_module_info_match (uri->module_info, info); gck_module_info_free (info); } return match; }
static void test_initialize_async (void) { GckModule *module; GAsyncResult *result; GError *error = NULL; /* Shouldn't be able to load modules */ gck_module_initialize_async (BUILDDIR "/.libs/libmock-test-module.so", NULL, fetch_async_result, &result); egg_test_wait_until (500); g_assert (result != NULL); /* Get the result */ module = gck_module_initialize_finish (result, &error); g_assert_no_error (error); g_assert (GCK_IS_MODULE (module)); g_object_unref (result); g_object_unref (module); }
/** * gck_module_get_slots: * @self: The module for which to get the slots. * @token_present: Whether to limit only to slots with a token present. * * Get the GckSlot objects for a given module. * * Return value: The possibly empty list of slots. Release this with gck_list_unref_free(). */ GList* gck_module_get_slots (GckModule *self, gboolean token_present) { CK_SLOT_ID_PTR slot_list; CK_ULONG count, i; GList *result; CK_RV rv; g_return_val_if_fail (GCK_IS_MODULE (self), NULL); g_return_val_if_fail (self->pv->funcs, NULL); rv = (self->pv->funcs->C_GetSlotList) (token_present ? CK_TRUE : CK_FALSE, NULL, &count); if (rv != CKR_OK) { g_warning ("couldn't get slot count: %s", gck_message_from_rv (rv)); return NULL; } if (!count) return NULL; slot_list = g_new (CK_SLOT_ID, count); rv = (self->pv->funcs->C_GetSlotList) (token_present ? CK_TRUE : CK_FALSE, slot_list, &count); if (rv != CKR_OK) { g_warning ("couldn't get slot list: %s", gck_message_from_rv (rv)); g_free (slot_list); return NULL; } result = NULL; for (i = 0; i < count; ++i) { result = g_list_prepend (result, g_object_new (GCK_TYPE_SLOT, "handle", slot_list[i], "module", self, NULL)); } g_free (slot_list); return g_list_reverse (result); }
gboolean _gck_call_sync (gpointer object, gpointer perform, gpointer complete, gpointer data, GCancellable *cancellable, GError **err) { GckArguments *args = (GckArguments*)data; GckModule *module = NULL; CK_RV rv; g_assert (!object || G_IS_OBJECT (object)); g_assert (perform); g_assert (args); if (object) { g_object_get (object, "module", &module, "handle", &args->handle, NULL); g_assert (GCK_IS_MODULE (module)); /* We now hold a reference to module until below */ args->pkcs11 = gck_module_get_functions (module); g_assert (args->pkcs11); } do { rv = perform_call (perform, cancellable, args); if (rv == CKR_FUNCTION_CANCELED) break; } while (!complete_call (complete, args, rv)); if (module) g_object_unref (module); if (rv == CKR_OK) return TRUE; g_set_error (err, GCK_ERROR, rv, "%s", gck_message_from_rv (rv)); return FALSE; }
/** * gck_slot_get_mechanism_info: * @self: The slot to get mechanism info from. * @mech_type: The mechanisms type to get info for. * * Get information for the specified mechanism. * * Return value: The mechanism information, or NULL if failed. Use * gck_mechanism_info_free() when done with it. **/ GckMechanismInfo* gck_slot_get_mechanism_info (GckSlot *self, gulong mech_type) { CK_SLOT_ID handle = (CK_SLOT_ID)-1; CK_FUNCTION_LIST_PTR funcs; GckMechanismInfo *mechinfo; GckModule *module = NULL; CK_MECHANISM_INFO info; struct tm; CK_RV rv; g_return_val_if_fail (GCK_IS_SLOT (self), NULL); g_object_get (self, "module", &module, "handle", &handle, NULL); g_return_val_if_fail (GCK_IS_MODULE (module), NULL); funcs = gck_module_get_functions (module); g_return_val_if_fail (funcs, NULL); memset (&info, 0, sizeof (info)); rv = (funcs->C_GetMechanismInfo) (handle, mech_type, &info); g_object_unref (module); if (rv != CKR_OK) { g_warning ("couldn't get mechanism info: %s", gck_message_from_rv (rv)); return NULL; } mechinfo = g_new0 (GckMechanismInfo, 1); mechinfo->flags = info.flags; mechinfo->max_key_size = info.ulMaxKeySize; mechinfo->min_key_size = info.ulMinKeySize; return mechinfo; }
/** * gck_module_get_functions: * @self: The module for which to get the function list. * * Get the PKCS#11 function list for the module. * * Return value: The function list, do not modify this structure. **/ CK_FUNCTION_LIST_PTR gck_module_get_functions (GckModule *self) { g_return_val_if_fail (GCK_IS_MODULE (self), NULL); return self->pv->funcs; }
/** * gck_module_get_path: * @self: The module for which to get the path. * * Get the file path of this module. This may not be an absolute path, and * usually reflects the path passed to gck_module_initialize(). * * Return value: The path, do not modify or free this value. **/ const gchar* gck_module_get_path (GckModule *self) { g_return_val_if_fail (GCK_IS_MODULE (self), NULL); return self->pv->path; }
/** * gck_slot_get_token_info: * @self: The slot to get info for. * * Get the token information for this slot. * * Return value: The token information. When done, use gck_token_info_free() * to release it. **/ GckTokenInfo* gck_slot_get_token_info (GckSlot *self) { CK_SLOT_ID handle = (CK_SLOT_ID)-1; CK_FUNCTION_LIST_PTR funcs; GckModule *module = NULL; GckTokenInfo *tokeninfo; CK_TOKEN_INFO info; gchar *string; struct tm tm; CK_RV rv; g_return_val_if_fail (GCK_IS_SLOT (self), NULL); g_object_get (self, "module", &module, "handle", &handle, NULL); g_return_val_if_fail (GCK_IS_MODULE (module), NULL); funcs = gck_module_get_functions (module); g_return_val_if_fail (funcs, NULL); memset (&info, 0, sizeof (info)); rv = (funcs->C_GetTokenInfo) (handle, &info); g_object_unref (module); if (rv != CKR_OK) { g_warning ("couldn't get slot info: %s", gck_message_from_rv (rv)); return NULL; } tokeninfo = g_new0 (GckTokenInfo, 1); tokeninfo->label = gck_string_from_chars (info.label, sizeof (info.label)); tokeninfo->model = gck_string_from_chars (info.model, sizeof (info.model)); tokeninfo->manufacturer_id = gck_string_from_chars (info.manufacturerID, sizeof (info.manufacturerID)); tokeninfo->serial_number = gck_string_from_chars (info.serialNumber, sizeof (info.serialNumber)); tokeninfo->flags = info.flags; tokeninfo->max_session_count = info.ulMaxSessionCount; tokeninfo->session_count = info.ulSessionCount; tokeninfo->max_rw_session_count = info.ulMaxRwSessionCount; tokeninfo->rw_session_count = info.ulRwSessionCount; tokeninfo->max_pin_len = info.ulMaxPinLen; tokeninfo->min_pin_len = info.ulMinPinLen; tokeninfo->total_public_memory = info.ulTotalPublicMemory; tokeninfo->total_private_memory = info.ulTotalPrivateMemory; tokeninfo->free_private_memory = info.ulFreePrivateMemory; tokeninfo->free_public_memory = info.ulFreePublicMemory; tokeninfo->hardware_version_major = info.hardwareVersion.major; tokeninfo->hardware_version_minor = info.hardwareVersion.minor; tokeninfo->firmware_version_major = info.firmwareVersion.major; tokeninfo->firmware_version_minor = info.firmwareVersion.minor; /* Parse the time into seconds since epoch */ if (info.flags & CKF_CLOCK_ON_TOKEN) { string = g_strndup ((gchar*)info.utcTime, MIN (14, sizeof (info.utcTime))); if (!strptime (string, "%Y%m%d%H%M%S", &tm)) tokeninfo->utc_time = -1; else tokeninfo->utc_time = timegm (&tm); g_free (string); } else { tokeninfo->utc_time = -1; } return tokeninfo; }